Rename GUI *.cpp to *.cc to match convention in core.
authorrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 25 Aug 2013 04:27:45 +0000 (04:27 +0000)
committerrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 25 Aug 2013 04:27:45 +0000 (04:27 +0000)
49 files changed:
gpsbabel/gui/aboutdlg.cc [new file with mode: 0644]
gpsbabel/gui/aboutdlg.cpp [deleted file]
gpsbabel/gui/advdlg.cc [new file with mode: 0644]
gpsbabel/gui/advdlg.cpp [deleted file]
gpsbabel/gui/app.pro
gpsbabel/gui/donate.cc [new file with mode: 0644]
gpsbabel/gui/donate.cpp [deleted file]
gpsbabel/gui/dpencode.cc [new file with mode: 0644]
gpsbabel/gui/dpencode.cpp [deleted file]
gpsbabel/gui/filterdata.cc [new file with mode: 0644]
gpsbabel/gui/filterdata.cpp [deleted file]
gpsbabel/gui/filterdlg.cc [new file with mode: 0644]
gpsbabel/gui/filterdlg.cpp [deleted file]
gpsbabel/gui/filterwidgets.cc [new file with mode: 0644]
gpsbabel/gui/filterwidgets.cpp [deleted file]
gpsbabel/gui/format.cc [new file with mode: 0644]
gpsbabel/gui/format.cpp [deleted file]
gpsbabel/gui/formatload.cc [new file with mode: 0644]
gpsbabel/gui/formatload.cpp [deleted file]
gpsbabel/gui/gmapdlg.cc [new file with mode: 0644]
gpsbabel/gui/gmapdlg.cpp [deleted file]
gpsbabel/gui/gpx.cc [new file with mode: 0644]
gpsbabel/gui/gpx.cpp [deleted file]
gpsbabel/gui/help.cc [new file with mode: 0644]
gpsbabel/gui/help.cpp [deleted file]
gpsbabel/gui/latlng.cc [new file with mode: 0644]
gpsbabel/gui/latlng.cpp [deleted file]
gpsbabel/gui/main.cc [new file with mode: 0644]
gpsbabel/gui/main.cpp [deleted file]
gpsbabel/gui/mainwindow.cc [new file with mode: 0644]
gpsbabel/gui/mainwindow.cpp [deleted file]
gpsbabel/gui/map.cc [new file with mode: 0644]
gpsbabel/gui/map.cpp [deleted file]
gpsbabel/gui/optionsdlg.cc [new file with mode: 0644]
gpsbabel/gui/optionsdlg.cpp [deleted file]
gpsbabel/gui/preferences.cc [new file with mode: 0644]
gpsbabel/gui/preferences.cpp [deleted file]
gpsbabel/gui/processwait.cc [new file with mode: 0644]
gpsbabel/gui/processwait.cpp [deleted file]
gpsbabel/gui/serial_mac.cc [new file with mode: 0644]
gpsbabel/gui/serial_mac.cpp [deleted file]
gpsbabel/gui/serial_unix.cc [new file with mode: 0644]
gpsbabel/gui/serial_unix.cpp [deleted file]
gpsbabel/gui/serial_win.cc [new file with mode: 0644]
gpsbabel/gui/serial_win.cpp [deleted file]
gpsbabel/gui/upgrade.cc [new file with mode: 0644]
gpsbabel/gui/upgrade.cpp [deleted file]
gpsbabel/gui/version_mismatch.cc [new file with mode: 0644]
gpsbabel/gui/version_mismatch.cpp [deleted file]

diff --git a/gpsbabel/gui/aboutdlg.cc b/gpsbabel/gui/aboutdlg.cc
new file mode 100644 (file)
index 0000000..e8b75f8
--- /dev/null
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+// $Id: aboutdlg.cpp,v 1.2 2010-01-17 21:57:00 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+
+#include "aboutdlg.h"
+#include "appname.h"
+#include "upgrade.h"
+
+AboutDlg::AboutDlg(QWidget *parent, const QString &ver1,
+                  const QString &ver2): QDialog(parent)
+{
+  ui.setupUi(this);
+  QTextDocument *doc = ui.textEdit->document();
+  ui.textEdit->setReadOnly(true);
+  QString tt = doc->toHtml();
+  tt.replace(QRegExp("\\$appname\\$"),  QString(appName));
+  tt.replace(QRegExp("\\$babelversion\\$"),  ver1);
+  tt.replace(QRegExp("\\$babelfeversion\\$"),  ver2);
+
+  // Not localized as it should never be seen.
+  tt.replace(QRegExp("\\$upgradetestmode\\$"),  
+    UpgradeCheck::isTestMode() ? "**Upgrade test mode**" : "");
+      
+  doc->setHtml(tt);
+  QTextCursor cur(doc);
+  cur.setPosition(0);
+  ui.textEdit->setTextCursor(cur);
+  ui.textEdit->ensureCursorVisible();
+}
diff --git a/gpsbabel/gui/aboutdlg.cpp b/gpsbabel/gui/aboutdlg.cpp
deleted file mode 100644 (file)
index e8b75f8..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// -*- C++ -*-
-// $Id: aboutdlg.cpp,v 1.2 2010-01-17 21:57:00 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-
-#include "aboutdlg.h"
-#include "appname.h"
-#include "upgrade.h"
-
-AboutDlg::AboutDlg(QWidget *parent, const QString &ver1,
-                  const QString &ver2): QDialog(parent)
-{
-  ui.setupUi(this);
-  QTextDocument *doc = ui.textEdit->document();
-  ui.textEdit->setReadOnly(true);
-  QString tt = doc->toHtml();
-  tt.replace(QRegExp("\\$appname\\$"),  QString(appName));
-  tt.replace(QRegExp("\\$babelversion\\$"),  ver1);
-  tt.replace(QRegExp("\\$babelfeversion\\$"),  ver2);
-
-  // Not localized as it should never be seen.
-  tt.replace(QRegExp("\\$upgradetestmode\\$"),  
-    UpgradeCheck::isTestMode() ? "**Upgrade test mode**" : "");
-      
-  doc->setHtml(tt);
-  QTextCursor cur(doc);
-  cur.setPosition(0);
-  ui.textEdit->setTextCursor(cur);
-  ui.textEdit->ensureCursorVisible();
-}
diff --git a/gpsbabel/gui/advdlg.cc b/gpsbabel/gui/advdlg.cc
new file mode 100644 (file)
index 0000000..ba2c255
--- /dev/null
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+// $Id: advdlg.cpp,v 1.3 2009-11-02 20:38:02 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+#include <QMessageBox>
+#include <QProcess>
+#include <QFileDialog>
+#include <QSettings>
+#include "advdlg.h"
+
+//------------------------------------------------------------------------
+AdvDlg::AdvDlg(QWidget* parent,
+              bool &synthShortNames,
+              bool &enableCharSetXform,
+              bool &previewGmap,
+              int  &debugLevel):
+  QDialog(parent),
+  synthShortNames(synthShortNames),
+  enableCharSetXform(enableCharSetXform),
+  previewGmap(previewGmap),
+  debugLevel(debugLevel)
+{
+  ui.setupUi(this);
+  ui.synthShortNames->setChecked(synthShortNames);
+  ui.enableCharSetXform->setChecked(enableCharSetXform);
+  ui.previewGmap->setChecked(previewGmap);
+  ui.debugCombo->setCurrentIndex(debugLevel+1);
+  ui.buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":images/ok"));
+  ui.buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":images/cancel"));
+  connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
+  connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
+}
+
+void AdvDlg::acceptClicked()
+{
+  synthShortNames = ui.synthShortNames->isChecked();
+  enableCharSetXform = ui.enableCharSetXform->isChecked();
+  previewGmap = ui.previewGmap->isChecked();
+  debugLevel = ui.debugCombo->currentIndex()-1;
+  accept();
+}
+
+void AdvDlg::rejectClicked()
+{
+  reject();
+}
diff --git a/gpsbabel/gui/advdlg.cpp b/gpsbabel/gui/advdlg.cpp
deleted file mode 100644 (file)
index ba2c255..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// -*- C++ -*-
-// $Id: advdlg.cpp,v 1.3 2009-11-02 20:38:02 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-#include <QMessageBox>
-#include <QProcess>
-#include <QFileDialog>
-#include <QSettings>
-#include "advdlg.h"
-
-//------------------------------------------------------------------------
-AdvDlg::AdvDlg(QWidget* parent,
-              bool &synthShortNames,
-              bool &enableCharSetXform,
-              bool &previewGmap,
-              int  &debugLevel):
-  QDialog(parent),
-  synthShortNames(synthShortNames),
-  enableCharSetXform(enableCharSetXform),
-  previewGmap(previewGmap),
-  debugLevel(debugLevel)
-{
-  ui.setupUi(this);
-  ui.synthShortNames->setChecked(synthShortNames);
-  ui.enableCharSetXform->setChecked(enableCharSetXform);
-  ui.previewGmap->setChecked(previewGmap);
-  ui.debugCombo->setCurrentIndex(debugLevel+1);
-  ui.buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":images/ok"));
-  ui.buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":images/cancel"));
-  connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
-  connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
-}
-
-void AdvDlg::acceptClicked()
-{
-  synthShortNames = ui.synthShortNames->isChecked();
-  enableCharSetXform = ui.enableCharSetXform->isChecked();
-  previewGmap = ui.previewGmap->isChecked();
-  debugLevel = ui.debugCombo->currentIndex()-1;
-  accept();
-}
-
-void AdvDlg::rejectClicked()
-{
-  reject();
-}
index 9cd9af0730dad9e2bd01f06180064a65ec84f202..bd14d2030fe2ef604b919c928396ab5bc091752e 100755 (executable)
@@ -48,30 +48,30 @@ FORMS += upgrade.ui
 FORMS += version_mismatch.ui
 FORMS += wayptsui.ui
 
-SOURCES += aboutdlg.cpp
-SOURCES += advdlg.cpp
-SOURCES += donate.cpp
-SOURCES += dpencode.cpp
-SOURCES += filterdata.cpp
-SOURCES += filterdlg.cpp
-SOURCES += filterwidgets.cpp
-SOURCES += format.cpp
-SOURCES += formatload.cpp
-SOURCES += gmapdlg.cpp
-SOURCES += gpx.cpp
-SOURCES += help.cpp
-SOURCES += latlng.cpp
-SOURCES += main.cpp
-SOURCES += mainwindow.cpp
-SOURCES += map.cpp
-SOURCES += optionsdlg.cpp
-SOURCES += preferences.cpp
-SOURCES += processwait.cpp
-SOURCES += upgrade.cpp
-SOURCES += version_mismatch.cpp
-macx:SOURCES += serial_mac.cpp
-unix:SOURCES += serial_unix.cpp
-windows:SOURCES += serial_win.cpp
+SOURCES += aboutdlg.cc
+SOURCES += advdlg.cc
+SOURCES += donate.cc
+SOURCES += dpencode.cc
+SOURCES += filterdata.cc
+SOURCES += filterdlg.cc
+SOURCES += filterwidgets.cc
+SOURCES += format.cc
+SOURCES += formatload.cc
+SOURCES += gmapdlg.cc
+SOURCES += gpx.cc
+SOURCES += help.cc
+SOURCES += latlng.cc
+SOURCES += main.cc
+SOURCES += mainwindow.cc
+SOURCES += map.cc
+SOURCES += optionsdlg.cc
+SOURCES += preferences.cc
+SOURCES += processwait.cc
+SOURCES += upgrade.cc
+SOURCES += version_mismatch.cc
+macx:SOURCES += serial_mac.cc
+unix:SOURCES += serial_unix.cc
+windows:SOURCES += serial_win.cc
 
 HEADERS += aboutdlg.h
 HEADERS += advdlg.h
diff --git a/gpsbabel/gui/donate.cc b/gpsbabel/gui/donate.cc
new file mode 100644 (file)
index 0000000..970c8bf
--- /dev/null
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2010  Robert Lipe <robertlipe@gpsbabel.org
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+
+#include "donate.h"
+#include <QUrl>
+#include <QDesktopServices>
+
+// A completely simple QDialog, in a class of its own for layout.
+Donate::Donate(QWidget *parent) : QDialog(parent)
+{
+  ui.setupUi(this);
+  connect(ui.contributeButton, SIGNAL(clicked()), this, SLOT(contributeClicked()));
+}
+
+void Donate::contributeClicked()
+{
+  QDesktopServices::openUrl(QUrl("http://www.gpsbabel.org/contribute.html"));
+  close();
+}
diff --git a/gpsbabel/gui/donate.cpp b/gpsbabel/gui/donate.cpp
deleted file mode 100644 (file)
index 970c8bf..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// -*- C++ -*-
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2010  Robert Lipe <robertlipe@gpsbabel.org
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-
-#include "donate.h"
-#include <QUrl>
-#include <QDesktopServices>
-
-// A completely simple QDialog, in a class of its own for layout.
-Donate::Donate(QWidget *parent) : QDialog(parent)
-{
-  ui.setupUi(this);
-  connect(ui.contributeButton, SIGNAL(clicked()), this, SLOT(contributeClicked()));
-}
-
-void Donate::contributeClicked()
-{
-  QDesktopServices::openUrl(QUrl("http://www.gpsbabel.org/contribute.html"));
-  close();
-}
diff --git a/gpsbabel/gui/dpencode.cc b/gpsbabel/gui/dpencode.cc
new file mode 100644 (file)
index 0000000..4fc683e
--- /dev/null
@@ -0,0 +1,204 @@
+// -*- C++ -*-
+// $Id: dpencode.cpp,v 1.3 2009-09-08 16:06:32 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Original in JavaScript: 
+//  PolylineEncoder.js copyright Mark McClure  April/May 2007
+//
+//  Translated to C++
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#include <stack>
+#include <math.h>
+#include "dpencode.h"
+
+using std::vector;
+using std::stack;
+using std::string;
+
+
+
+//------------------------------------------------------------------------
+PolylineEncoder::PolylineEncoder(int numLevels, double zoomFactor, double vs):
+  numLevels(numLevels), zoomFactor(zoomFactor), verySmall(vs)
+{
+  if (verySmall <=0.0)
+    verySmall = 1.0E-5;
+  for(int i = 0; i < numLevels; i++)
+    zoomLevelBreaks.push_back(verySmall*pow(zoomFactor, numLevels-i-1));
+}
+
+//------------------------------------------------------------------------
+class IntervalPair
+{
+public:
+  IntervalPair(int i0, int i1): i0(i0), i1(i1) {
+  }
+  int  i0, i1;
+};
+
+//------------------------------------------------------------------------
+static double hypotenuse(double a, double b){
+  return sqrt(a*a + b*b);
+}
+//------------------------------------------------------------------------
+static double hdist(const LatLng &a, const LatLng &b) {
+  return hypotenuse(a.lat()-b.lat(), a.lng()-b.lng());
+}
+
+//------------------------------------------------------------------------
+static string encodeNumber(int num) 
+{
+  string encodeString = "";
+  while (num >= 0x20) {
+    encodeString += char((0x20 | (num & 0x1f)) + 63);
+    num = num >> 5;
+  }
+  encodeString += char(num + 63);
+  return encodeString;
+}
+
+//------------------------------------------------------------------------
+// This one is Google's verbatim.
+static string encodeSignedNumber (int num) 
+{
+  int sgn_num = num << 1;
+  if (num < 0) {
+    sgn_num = ~(sgn_num);
+  }
+  return(encodeNumber(sgn_num));
+}
+
+//------------------------------------------------------------------------
+int roundToInt(double x) {
+  return (x>0.0) ? int(x+0.5) : int(x-0.5);
+}
+//------------------------------------------------------------------------
+void PolylineEncoder::createEncodings(string &encoded_points,
+                                     const vector <LatLng> &points,
+                                     const vector <double> &dists)
+{
+  encoded_points = "";;
+  int plat = 0;
+  int plng = 0;
+  for(unsigned int i = 0; i < points.size(); i++) {
+    if(dists[i] >= 0.0 || i == 0 || i == points.size()-1) {
+      int late5 = roundToInt(points[i].lat() * 1e5);
+      int lnge5 = roundToInt(points[i].lng() * 1e5);
+      int dlat = late5 - plat;
+      int dlng = lnge5 - plng;
+      encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
+      plat = late5;
+      plng = lnge5;
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+// This computes the appropriate zoom level of a point in terms of it's
+// distance from the relevant segment in the DP algorithm.  Could be done
+// in terms of a logarithm, but this approach makes it a bit easier to
+// ensure that the level is not too large.
+int PolylineEncoder::computeLevel(double dd)
+{
+  int lev = 0;
+  if(dd > verySmall) {
+    while(dd < zoomLevelBreaks[lev]) {
+      lev++;
+    }
+  }
+  return lev;
+}
+//------------------------------------------------------------------------
+// Now we can use the previous function to march down the list
+// of points and encode the levels.  Like createEncodings, we
+// ignore points whose distance (in dists) is undefined.
+void PolylineEncoder::encodeLevels(string &encoded_levels, const vector<LatLng> &points, const vector<double>&dists)
+{
+  encoded_levels = "";
+  encoded_levels += encodeNumber(numLevels-1);
+  for (unsigned int i=1; i<points.size()-1; i++) {
+    if(dists[i] >= 0.0) {
+      encoded_levels += encodeNumber(numLevels-computeLevel(dists[i])-1);
+    }
+  }
+  encoded_levels += encodeNumber(numLevels-1);
+}
+
+
+//------------------------------------------------------------------------
+double PolylineEncoder::distance(const LatLng &p0, const LatLng &p1, const LatLng &p2) 
+{
+  double out = 0.0;
+  if (p1.lat() == p2.lat() && p1.lng() == p2.lng()) {
+    out = hdist(p2, p0);
+  }
+  else {
+    double dlat = (p2.lat()-p1.lat());
+    double dlng = (p2.lng()-p1.lng());
+    double u = ((p0.lat()-p1.lat())*dlat+(p0.lng()-p1.lng())*dlng)/(dlat*dlat + dlng*dlng);
+  
+    if (u <= 0) {
+      out = hdist(p0, p1);
+    }
+    else if(u >= 1) {
+      out = hdist(p0, p2);
+    }
+    else {
+      out = hdist(p0, LatLng(p1.lat() + u*dlat, p1.lng() + u*dlng));
+    }
+  }
+  return out;
+}
+
+//------------------------------------------------------------------------
+void PolylineEncoder::dpEncode(string &encPts, string &encLevels, const vector<LatLng> &points)
+{
+  if (points.size() < 2) {
+    encPts = encLevels = "";  // no solution here.
+    return;
+
+  }
+  stack <IntervalPair> stk;
+  vector <double>  dists(points.size(), -1.0);
+  
+  stk.push(IntervalPair(0, int(points.size())-1));
+  while (!stk.empty()) {
+    
+    IntervalPair current = stk.top();
+    stk.pop();
+    
+    double maxDist = -1.0;
+    int maxLoc = -1;
+    for (int i=current.i0+1; i<current.i1; i++) {
+      double dist = this->distance(points[i], points[current.i0], points[current.i1]);
+      if(dist > maxDist) {
+       maxDist = dist;
+       maxLoc = i;
+      }
+    }
+    if(maxDist > this->verySmall) {
+      dists[maxLoc] = maxDist;
+      stk.push(IntervalPair(current.i0, maxLoc));
+      stk.push(IntervalPair(maxLoc, current.i1));
+    }
+  }
+  createEncodings(encPts, points, dists);
+  encodeLevels(encLevels, points, dists);
+}
diff --git a/gpsbabel/gui/dpencode.cpp b/gpsbabel/gui/dpencode.cpp
deleted file mode 100644 (file)
index 4fc683e..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-// -*- C++ -*-
-// $Id: dpencode.cpp,v 1.3 2009-09-08 16:06:32 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Original in JavaScript: 
-//  PolylineEncoder.js copyright Mark McClure  April/May 2007
-//
-//  Translated to C++
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#include <stack>
-#include <math.h>
-#include "dpencode.h"
-
-using std::vector;
-using std::stack;
-using std::string;
-
-
-
-//------------------------------------------------------------------------
-PolylineEncoder::PolylineEncoder(int numLevels, double zoomFactor, double vs):
-  numLevels(numLevels), zoomFactor(zoomFactor), verySmall(vs)
-{
-  if (verySmall <=0.0)
-    verySmall = 1.0E-5;
-  for(int i = 0; i < numLevels; i++)
-    zoomLevelBreaks.push_back(verySmall*pow(zoomFactor, numLevels-i-1));
-}
-
-//------------------------------------------------------------------------
-class IntervalPair
-{
-public:
-  IntervalPair(int i0, int i1): i0(i0), i1(i1) {
-  }
-  int  i0, i1;
-};
-
-//------------------------------------------------------------------------
-static double hypotenuse(double a, double b){
-  return sqrt(a*a + b*b);
-}
-//------------------------------------------------------------------------
-static double hdist(const LatLng &a, const LatLng &b) {
-  return hypotenuse(a.lat()-b.lat(), a.lng()-b.lng());
-}
-
-//------------------------------------------------------------------------
-static string encodeNumber(int num) 
-{
-  string encodeString = "";
-  while (num >= 0x20) {
-    encodeString += char((0x20 | (num & 0x1f)) + 63);
-    num = num >> 5;
-  }
-  encodeString += char(num + 63);
-  return encodeString;
-}
-
-//------------------------------------------------------------------------
-// This one is Google's verbatim.
-static string encodeSignedNumber (int num) 
-{
-  int sgn_num = num << 1;
-  if (num < 0) {
-    sgn_num = ~(sgn_num);
-  }
-  return(encodeNumber(sgn_num));
-}
-
-//------------------------------------------------------------------------
-int roundToInt(double x) {
-  return (x>0.0) ? int(x+0.5) : int(x-0.5);
-}
-//------------------------------------------------------------------------
-void PolylineEncoder::createEncodings(string &encoded_points,
-                                     const vector <LatLng> &points,
-                                     const vector <double> &dists)
-{
-  encoded_points = "";;
-  int plat = 0;
-  int plng = 0;
-  for(unsigned int i = 0; i < points.size(); i++) {
-    if(dists[i] >= 0.0 || i == 0 || i == points.size()-1) {
-      int late5 = roundToInt(points[i].lat() * 1e5);
-      int lnge5 = roundToInt(points[i].lng() * 1e5);
-      int dlat = late5 - plat;
-      int dlng = lnge5 - plng;
-      encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
-      plat = late5;
-      plng = lnge5;
-    }
-  }
-}
-
-//------------------------------------------------------------------------
-// This computes the appropriate zoom level of a point in terms of it's
-// distance from the relevant segment in the DP algorithm.  Could be done
-// in terms of a logarithm, but this approach makes it a bit easier to
-// ensure that the level is not too large.
-int PolylineEncoder::computeLevel(double dd)
-{
-  int lev = 0;
-  if(dd > verySmall) {
-    while(dd < zoomLevelBreaks[lev]) {
-      lev++;
-    }
-  }
-  return lev;
-}
-//------------------------------------------------------------------------
-// Now we can use the previous function to march down the list
-// of points and encode the levels.  Like createEncodings, we
-// ignore points whose distance (in dists) is undefined.
-void PolylineEncoder::encodeLevels(string &encoded_levels, const vector<LatLng> &points, const vector<double>&dists)
-{
-  encoded_levels = "";
-  encoded_levels += encodeNumber(numLevels-1);
-  for (unsigned int i=1; i<points.size()-1; i++) {
-    if(dists[i] >= 0.0) {
-      encoded_levels += encodeNumber(numLevels-computeLevel(dists[i])-1);
-    }
-  }
-  encoded_levels += encodeNumber(numLevels-1);
-}
-
-
-//------------------------------------------------------------------------
-double PolylineEncoder::distance(const LatLng &p0, const LatLng &p1, const LatLng &p2) 
-{
-  double out = 0.0;
-  if (p1.lat() == p2.lat() && p1.lng() == p2.lng()) {
-    out = hdist(p2, p0);
-  }
-  else {
-    double dlat = (p2.lat()-p1.lat());
-    double dlng = (p2.lng()-p1.lng());
-    double u = ((p0.lat()-p1.lat())*dlat+(p0.lng()-p1.lng())*dlng)/(dlat*dlat + dlng*dlng);
-  
-    if (u <= 0) {
-      out = hdist(p0, p1);
-    }
-    else if(u >= 1) {
-      out = hdist(p0, p2);
-    }
-    else {
-      out = hdist(p0, LatLng(p1.lat() + u*dlat, p1.lng() + u*dlng));
-    }
-  }
-  return out;
-}
-
-//------------------------------------------------------------------------
-void PolylineEncoder::dpEncode(string &encPts, string &encLevels, const vector<LatLng> &points)
-{
-  if (points.size() < 2) {
-    encPts = encLevels = "";  // no solution here.
-    return;
-
-  }
-  stack <IntervalPair> stk;
-  vector <double>  dists(points.size(), -1.0);
-  
-  stk.push(IntervalPair(0, int(points.size())-1));
-  while (!stk.empty()) {
-    
-    IntervalPair current = stk.top();
-    stk.pop();
-    
-    double maxDist = -1.0;
-    int maxLoc = -1;
-    for (int i=current.i0+1; i<current.i1; i++) {
-      double dist = this->distance(points[i], points[current.i0], points[current.i1]);
-      if(dist > maxDist) {
-       maxDist = dist;
-       maxLoc = i;
-      }
-    }
-    if(maxDist > this->verySmall) {
-      dists[maxLoc] = maxDist;
-      stk.push(IntervalPair(current.i0, maxLoc));
-      stk.push(IntervalPair(maxLoc, current.i1));
-    }
-  }
-  createEncodings(encPts, points, dists);
-  encodeLevels(encLevels, points, dists);
-}
diff --git a/gpsbabel/gui/filterdata.cc b/gpsbabel/gui/filterdata.cc
new file mode 100644 (file)
index 0000000..53ac7d9
--- /dev/null
@@ -0,0 +1,176 @@
+// -*- C++ -*-
+// $Id: filterdata.cpp,v 1.4 2009-11-02 20:38:02 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+
+#include "filterdata.h"
+
+QStringList WayPtsFilterData::makeOptionString()
+{
+  QStringList args;
+  if (!inUse)
+    return args;
+
+  if (radius) {
+    args << QString("-x");
+    args << QString("radius,distance=%1%2,lat=%3,lon=%4")
+      .arg(radiusVal).arg("MK"[radiusUnit]).arg(latVal, 0, 'f', 8).arg(longVal, 0, 'f', 8);
+  }
+  if (duplicates && (shortNames ^ locations)) {
+    args << QString("-x");
+    QString s = "duplicate";
+    if (shortNames)
+      s += ",shortname";
+    if (locations)
+      s += ",location";
+    args << s;
+  }
+
+  if (position) {
+    args << QString("-x");
+    args << QString("position,distance=%1%2").arg(positionVal).arg("FM"[positionUnit]);
+  }
+  return args;
+}
+
+//------------------------------------------------------------------------
+static QString optionDate(const QDateTime &dt, bool useLocal)
+{
+  QDateTime d;
+  if (useLocal) {
+    d = dt.toLocalTime();
+  }
+  else {
+    d = dt.toUTC();
+  }
+
+  QDate date = d.date();
+  QTime time = d.time();
+  QString s = QString("%1%2%3%4%5%6")
+    .arg(date.year(),   4, 10, QChar('0'))
+    .arg(date.month(),  2, 10, QChar('0'))
+    .arg(date.day(),    2, 10, QChar('0'))
+    .arg(time.hour(),   2, 10, QChar('0'))
+    .arg(time.minute(), 2, 10, QChar('0'))
+    .arg(time.second(), 2, 10, QChar('0'));
+  return s;
+}
+
+//------------------------------------------------------------------------
+QStringList TrackFilterData::makeOptionString()
+{
+  static const char *fixStrings[] = {"none", "pps", "dgpss", "3d", "2d"}; // match with designer!
+  QStringList args;
+  if (!inUse)
+    return args;
+
+  QString s;
+  if (GPSFixes) s += QString(",fix=%1").arg(fixStrings[GPSFixesVal]);
+  if (course)   s += ",course";
+  if (speed)    s += ",speed";
+  if (pack)     s += ",pack";
+  if (merge)    s += ",merge";
+  if (pack || merge) {
+    if (splitByDate)  {
+      s += ",split";
+    }
+    if (splitByTime)  {
+      s += ",split";
+      if (splitTime > 0)
+       s += QString("=%1%2").arg(splitTime).arg("mhd"[splitTimeUnit]);
+    }
+    if (splitByDistance && splitDist > 0) {
+      double d = splitDist;
+      char u = ' ';
+      if (splitDistUnit == 0) { // ft.
+       d /= 5280.0;  u = 'm';
+      }
+      else if (splitDistUnit == 1) { //m
+       d /= 1000.0;  u = 'k';
+      }
+      else if (splitDistUnit == 2) { //km
+       u = 'k';
+      }
+      else if (splitDistUnit == 3) { //m
+       u = 'm';
+      }
+      s += QString(",sdistance=%1%2").arg(d).arg(u);
+    }
+  }
+
+  if (start)    s += QString(",start=%1").arg(optionDate(startTime, TZ));
+  if (stop)     s += QString(",stop=%1").arg(optionDate(stopTime, TZ));
+  if (move)     s += QString(",move=%1d%2h%3m%4s").arg(days).arg(hours).arg(mins).arg(secs);
+  if (title)    s += QString(",title=%1").arg(titleString);
+
+  if (s.length())
+    args << "-x" << "track" + s;
+
+  return args;
+}
+
+//------------------------------------------------------------------------
+QStringList RtTrkFilterData::makeOptionString()
+{
+  QStringList args;
+  if (!inUse)
+    return args;
+
+  if (reverse)  args << QString("-x") << QString("reverse");
+  if (simplify) args << QString("-x") << QString("simplify,count=%1").arg(limitTo);
+
+  return args;
+}
+
+//------------------------------------------------------------------------
+QStringList MiscFltFilterData::makeOptionString()
+{
+  QStringList args;
+  if (!inUse)
+    return args;
+
+  if (nukeRoutes || nukeTracks || nukeWaypoints) {
+    args << QString("-x");
+    QString s = "nuketypes";
+    if (nukeRoutes) s += ",routes";
+    if (nukeTracks) s += ",tracks";
+    if (nukeWaypoints) s += ",waypoints";
+    args << s;
+  }
+
+  if (swap) args << "-x" << "swap";
+
+  if (transform) {
+    static const char *xformStr[] = {
+      "wpt=trk",
+      "trk=rte",
+      "rte=wpt",
+      "wpt=rte",
+      "rte=trk",
+      "trk=wpt",
+    };
+    args << QString("-x");
+    QString s= QString("transform,%1").arg(xformStr[transformVal]);
+    if (del) s += ",del";
+    args << s;
+  }
+  return args;
+}
diff --git a/gpsbabel/gui/filterdata.cpp b/gpsbabel/gui/filterdata.cpp
deleted file mode 100644 (file)
index 53ac7d9..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// -*- C++ -*-
-// $Id: filterdata.cpp,v 1.4 2009-11-02 20:38:02 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-
-#include "filterdata.h"
-
-QStringList WayPtsFilterData::makeOptionString()
-{
-  QStringList args;
-  if (!inUse)
-    return args;
-
-  if (radius) {
-    args << QString("-x");
-    args << QString("radius,distance=%1%2,lat=%3,lon=%4")
-      .arg(radiusVal).arg("MK"[radiusUnit]).arg(latVal, 0, 'f', 8).arg(longVal, 0, 'f', 8);
-  }
-  if (duplicates && (shortNames ^ locations)) {
-    args << QString("-x");
-    QString s = "duplicate";
-    if (shortNames)
-      s += ",shortname";
-    if (locations)
-      s += ",location";
-    args << s;
-  }
-
-  if (position) {
-    args << QString("-x");
-    args << QString("position,distance=%1%2").arg(positionVal).arg("FM"[positionUnit]);
-  }
-  return args;
-}
-
-//------------------------------------------------------------------------
-static QString optionDate(const QDateTime &dt, bool useLocal)
-{
-  QDateTime d;
-  if (useLocal) {
-    d = dt.toLocalTime();
-  }
-  else {
-    d = dt.toUTC();
-  }
-
-  QDate date = d.date();
-  QTime time = d.time();
-  QString s = QString("%1%2%3%4%5%6")
-    .arg(date.year(),   4, 10, QChar('0'))
-    .arg(date.month(),  2, 10, QChar('0'))
-    .arg(date.day(),    2, 10, QChar('0'))
-    .arg(time.hour(),   2, 10, QChar('0'))
-    .arg(time.minute(), 2, 10, QChar('0'))
-    .arg(time.second(), 2, 10, QChar('0'));
-  return s;
-}
-
-//------------------------------------------------------------------------
-QStringList TrackFilterData::makeOptionString()
-{
-  static const char *fixStrings[] = {"none", "pps", "dgpss", "3d", "2d"}; // match with designer!
-  QStringList args;
-  if (!inUse)
-    return args;
-
-  QString s;
-  if (GPSFixes) s += QString(",fix=%1").arg(fixStrings[GPSFixesVal]);
-  if (course)   s += ",course";
-  if (speed)    s += ",speed";
-  if (pack)     s += ",pack";
-  if (merge)    s += ",merge";
-  if (pack || merge) {
-    if (splitByDate)  {
-      s += ",split";
-    }
-    if (splitByTime)  {
-      s += ",split";
-      if (splitTime > 0)
-       s += QString("=%1%2").arg(splitTime).arg("mhd"[splitTimeUnit]);
-    }
-    if (splitByDistance && splitDist > 0) {
-      double d = splitDist;
-      char u = ' ';
-      if (splitDistUnit == 0) { // ft.
-       d /= 5280.0;  u = 'm';
-      }
-      else if (splitDistUnit == 1) { //m
-       d /= 1000.0;  u = 'k';
-      }
-      else if (splitDistUnit == 2) { //km
-       u = 'k';
-      }
-      else if (splitDistUnit == 3) { //m
-       u = 'm';
-      }
-      s += QString(",sdistance=%1%2").arg(d).arg(u);
-    }
-  }
-
-  if (start)    s += QString(",start=%1").arg(optionDate(startTime, TZ));
-  if (stop)     s += QString(",stop=%1").arg(optionDate(stopTime, TZ));
-  if (move)     s += QString(",move=%1d%2h%3m%4s").arg(days).arg(hours).arg(mins).arg(secs);
-  if (title)    s += QString(",title=%1").arg(titleString);
-
-  if (s.length())
-    args << "-x" << "track" + s;
-
-  return args;
-}
-
-//------------------------------------------------------------------------
-QStringList RtTrkFilterData::makeOptionString()
-{
-  QStringList args;
-  if (!inUse)
-    return args;
-
-  if (reverse)  args << QString("-x") << QString("reverse");
-  if (simplify) args << QString("-x") << QString("simplify,count=%1").arg(limitTo);
-
-  return args;
-}
-
-//------------------------------------------------------------------------
-QStringList MiscFltFilterData::makeOptionString()
-{
-  QStringList args;
-  if (!inUse)
-    return args;
-
-  if (nukeRoutes || nukeTracks || nukeWaypoints) {
-    args << QString("-x");
-    QString s = "nuketypes";
-    if (nukeRoutes) s += ",routes";
-    if (nukeTracks) s += ",tracks";
-    if (nukeWaypoints) s += ",waypoints";
-    args << s;
-  }
-
-  if (swap) args << "-x" << "swap";
-
-  if (transform) {
-    static const char *xformStr[] = {
-      "wpt=trk",
-      "trk=rte",
-      "rte=wpt",
-      "wpt=rte",
-      "rte=trk",
-      "trk=wpt",
-    };
-    args << QString("-x");
-    QString s= QString("transform,%1").arg(xformStr[transformVal]);
-    if (del) s += ",del";
-    args << s;
-  }
-  return args;
-}
diff --git a/gpsbabel/gui/filterdlg.cc b/gpsbabel/gui/filterdlg.cc
new file mode 100644 (file)
index 0000000..4cc2fee
--- /dev/null
@@ -0,0 +1,134 @@
+// -*- C++ -*-
+// $Id: filterdlg.cpp,v 1.4 2009-09-08 16:06:32 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+
+#include <QMessageBox>
+#include "filterdlg.h"
+#include "help.h"
+#include "appname.h"
+
+int FilterDialog::lastPage = 0;
+
+FilterDialog::FilterDialog(QWidget*parent, AllFiltersData &fd): QDialog(parent), fd(fd)
+{
+  ui.setupUi(this);
+  ui.filterList->clear();
+
+  widgetStack = new QStackedWidget(ui.frame);
+  QHBoxLayout *layout = new QHBoxLayout(ui.frame);
+  layout->addWidget(widgetStack);
+  layout->setContentsMargins(2, 2, 2, 2);
+
+  addFilterPage(tr("Tracks"),
+               new TrackWidget(widgetStack, fd.trackFilterData), &fd.trackFilterData.inUse);
+
+  addFilterPage(tr("Waypoints"),
+               new WayPtsWidget(widgetStack, fd.wayPtsFilterData), &fd.wayPtsFilterData.inUse);
+
+  addFilterPage(tr("Routes & Tracks"),
+               new RtTrkWidget(widgetStack, fd.rtTrkFilterData), &fd.rtTrkFilterData.inUse);
+
+  addFilterPage(tr("Miscellaneous"),
+               new MiscFltWidget(widgetStack, fd.miscFltFilterData), &fd.miscFltFilterData.inUse);
+
+  connect(ui.filterList, SIGNAL(currentRowChanged(int)),
+         this, SLOT(pageSelectionChanged(int)));
+
+  connect(ui.filterList, SIGNAL(itemClicked(QListWidgetItem *)),
+         this, SLOT(itemClickedX(QListWidgetItem*)));
+
+  connect(ui.helpButton, SIGNAL(clicked()), this, SLOT(helpX()));
+  connect(ui.resetButton, SIGNAL(clicked()), this, SLOT(resetX()));
+
+
+  ui.buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":images/ok"));
+  ui.buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":images/cancel"));
+
+  ui.filterList->setCurrentRow(lastPage);
+
+  // So that it occupies minimum space.
+  this->resize(100, 100);
+}
+
+
+//------------------------------------------------------------------------
+void FilterDialog::addFilterPage(const QString &name, FilterWidget *fw, bool*use)
+{
+  QListWidgetItem *it = new QListWidgetItem(name);
+  it->setCheckState(*use? Qt::Checked:Qt::Unchecked);
+  fw->setEnabled(*use);
+  ui.filterList->addItem(it);
+  widgetStack->addWidget(fw);
+  pages    << fw;
+  usePages << use;
+}
+
+//------------------------------------------------------------------------
+void FilterDialog::itemClickedX(QListWidgetItem *it)
+{
+  int row = ui.filterList->row(it);
+  bool b = (it->checkState() == Qt::Checked);
+  pages[row]->setEnabled(b);
+  pages[row]->checkChecks();
+}
+//------------------------------------------------------------------------
+void FilterDialog::pageSelectionChanged(int i)
+{
+  widgetStack->setCurrentWidget(pages[i]);
+}
+
+//------------------------------------------------------------------------
+void FilterDialog::resetX()
+{
+  int ret = QMessageBox::warning
+    (this, QString(appName),
+     tr("Are you sure you want to reset all filter options to default values?"),
+     QMessageBox::Yes | QMessageBox::No);
+
+  if (ret == QMessageBox::Yes) {
+    fd.defaultAll();
+    for (int i=0; i<pages.size(); i++) {
+      pages[i]->setWidgetValues();
+      pages[i]->setEnabled(*(usePages[i]));
+      pages[i]->checkChecks();
+      ui.filterList->item(i)->setCheckState(*(usePages[i]) ? Qt::Checked: Qt::Unchecked);
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+void FilterDialog::helpX()
+{
+  ShowHelp("Data_Filters.html");
+}
+
+//------------------------------------------------------------------------
+void FilterDialog::runDialog()
+{
+  if (exec()) {
+    for (int i=0; i<pages.size(); i++) {
+      pages[i]->getWidgetValues();
+      *(usePages[i]) = ui.filterList->item(i)->checkState() == Qt::Checked;
+    }
+  }
+  lastPage = ui.filterList->currentRow();
+}
diff --git a/gpsbabel/gui/filterdlg.cpp b/gpsbabel/gui/filterdlg.cpp
deleted file mode 100644 (file)
index 4cc2fee..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-// -*- C++ -*-
-// $Id: filterdlg.cpp,v 1.4 2009-09-08 16:06:32 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-
-#include <QMessageBox>
-#include "filterdlg.h"
-#include "help.h"
-#include "appname.h"
-
-int FilterDialog::lastPage = 0;
-
-FilterDialog::FilterDialog(QWidget*parent, AllFiltersData &fd): QDialog(parent), fd(fd)
-{
-  ui.setupUi(this);
-  ui.filterList->clear();
-
-  widgetStack = new QStackedWidget(ui.frame);
-  QHBoxLayout *layout = new QHBoxLayout(ui.frame);
-  layout->addWidget(widgetStack);
-  layout->setContentsMargins(2, 2, 2, 2);
-
-  addFilterPage(tr("Tracks"),
-               new TrackWidget(widgetStack, fd.trackFilterData), &fd.trackFilterData.inUse);
-
-  addFilterPage(tr("Waypoints"),
-               new WayPtsWidget(widgetStack, fd.wayPtsFilterData), &fd.wayPtsFilterData.inUse);
-
-  addFilterPage(tr("Routes & Tracks"),
-               new RtTrkWidget(widgetStack, fd.rtTrkFilterData), &fd.rtTrkFilterData.inUse);
-
-  addFilterPage(tr("Miscellaneous"),
-               new MiscFltWidget(widgetStack, fd.miscFltFilterData), &fd.miscFltFilterData.inUse);
-
-  connect(ui.filterList, SIGNAL(currentRowChanged(int)),
-         this, SLOT(pageSelectionChanged(int)));
-
-  connect(ui.filterList, SIGNAL(itemClicked(QListWidgetItem *)),
-         this, SLOT(itemClickedX(QListWidgetItem*)));
-
-  connect(ui.helpButton, SIGNAL(clicked()), this, SLOT(helpX()));
-  connect(ui.resetButton, SIGNAL(clicked()), this, SLOT(resetX()));
-
-
-  ui.buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":images/ok"));
-  ui.buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":images/cancel"));
-
-  ui.filterList->setCurrentRow(lastPage);
-
-  // So that it occupies minimum space.
-  this->resize(100, 100);
-}
-
-
-//------------------------------------------------------------------------
-void FilterDialog::addFilterPage(const QString &name, FilterWidget *fw, bool*use)
-{
-  QListWidgetItem *it = new QListWidgetItem(name);
-  it->setCheckState(*use? Qt::Checked:Qt::Unchecked);
-  fw->setEnabled(*use);
-  ui.filterList->addItem(it);
-  widgetStack->addWidget(fw);
-  pages    << fw;
-  usePages << use;
-}
-
-//------------------------------------------------------------------------
-void FilterDialog::itemClickedX(QListWidgetItem *it)
-{
-  int row = ui.filterList->row(it);
-  bool b = (it->checkState() == Qt::Checked);
-  pages[row]->setEnabled(b);
-  pages[row]->checkChecks();
-}
-//------------------------------------------------------------------------
-void FilterDialog::pageSelectionChanged(int i)
-{
-  widgetStack->setCurrentWidget(pages[i]);
-}
-
-//------------------------------------------------------------------------
-void FilterDialog::resetX()
-{
-  int ret = QMessageBox::warning
-    (this, QString(appName),
-     tr("Are you sure you want to reset all filter options to default values?"),
-     QMessageBox::Yes | QMessageBox::No);
-
-  if (ret == QMessageBox::Yes) {
-    fd.defaultAll();
-    for (int i=0; i<pages.size(); i++) {
-      pages[i]->setWidgetValues();
-      pages[i]->setEnabled(*(usePages[i]));
-      pages[i]->checkChecks();
-      ui.filterList->item(i)->setCheckState(*(usePages[i]) ? Qt::Checked: Qt::Unchecked);
-    }
-  }
-}
-
-//------------------------------------------------------------------------
-void FilterDialog::helpX()
-{
-  ShowHelp("Data_Filters.html");
-}
-
-//------------------------------------------------------------------------
-void FilterDialog::runDialog()
-{
-  if (exec()) {
-    for (int i=0; i<pages.size(); i++) {
-      pages[i]->getWidgetValues();
-      *(usePages[i]) = ui.filterList->item(i)->checkState() == Qt::Checked;
-    }
-  }
-  lastPage = ui.filterList->currentRow();
-}
diff --git a/gpsbabel/gui/filterwidgets.cc b/gpsbabel/gui/filterwidgets.cc
new file mode 100644 (file)
index 0000000..09990ed
--- /dev/null
@@ -0,0 +1,240 @@
+// -*- C++ -*-
+// $Id: filterwidgets.cpp,v 1.5 2009-11-02 20:38:02 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+
+#include "filterwidgets.h"
+
+
+//------------------------------------------------------------------------
+TrackWidget::TrackWidget(QWidget *parent, TrackFilterData &tfd): FilterWidget(parent) , tfd(tfd)
+{
+  ui.setupUi(this);
+
+  // Checkbox interlocks
+  addCheckEnabler(ui.titleCheck, ui.titleText);
+  addCheckEnabler(ui.moveCheck,
+                 (QList<QWidget *> ()
+                  << ui.daysLabel << ui.daysSpin
+                  << ui.hoursLabel<< ui.hoursSpin
+                  << ui.minsLabel << ui.minsSpin
+                  << ui.secsLabel << ui.secsSpin));
+  addCheckEnabler(ui.startCheck,    ui.startEdit);
+  addCheckEnabler(ui.stopCheck,     ui.stopEdit);
+  addCheckEnabler(ui.GPSFixesCheck, ui.GPSFixesCombo);
+
+  addCheckEnabler(ui.splitTimeCheck, 
+                 (QList<QWidget *> ()
+                  <<ui.splitTimeSpin
+                  <<ui.splitTimeCombo));
+  addCheckEnabler(ui.splitDistanceCheck, 
+                 (QList<QWidget *> ()
+                  <<ui.splitDistSpin
+                  <<ui.splitDistCombo));
+
+  connect(ui.mergeCheck, SIGNAL(clicked()) , this, SLOT(mergeCheckX()));
+  connect(ui.packCheck,  SIGNAL(clicked()),  this, SLOT(packCheckX()));
+  connect(ui.startCheck, SIGNAL(clicked()),  this, SLOT(otherCheckX()));
+  connect(ui.stopCheck,   SIGNAL(clicked()), this, SLOT(otherCheckX()));
+
+  connect(ui.splitDateCheck,   SIGNAL(clicked()), this, SLOT(splitDateX()));
+  connect(ui.splitTimeCheck,   SIGNAL(clicked()), this, SLOT(splitTimeX()));
+  connect(ui.splitDistanceCheck,   SIGNAL(clicked()), this, SLOT(splitDistanceX()));
+
+  ui.startEdit->setDisplayFormat("dd MMM yyyy hh:mm:ss AP");
+  ui.stopEdit->setDisplayFormat("dd MMM yyyy hh:mm:ss AP");
+
+  // Collect the data fields.
+  fopts << new BoolFilterOption(tfd.title,  ui.titleCheck);
+  fopts << new BoolFilterOption(tfd.move,   ui.moveCheck);
+  fopts << new BoolFilterOption(tfd.TZ,     ui.TZCheck);
+  fopts << new BoolFilterOption(tfd.start,  ui.startCheck);
+  fopts << new BoolFilterOption(tfd.stop,   ui.stopCheck);
+  fopts << new BoolFilterOption(tfd.pack,   ui.packCheck);
+  fopts << new BoolFilterOption(tfd.merge,  ui.mergeCheck);
+  fopts << new BoolFilterOption(tfd.splitByDate,  ui.splitDateCheck);
+  fopts << new BoolFilterOption(tfd.splitByTime,  ui.splitTimeCheck);
+  fopts << new BoolFilterOption(tfd.splitByDistance,  ui.splitDistanceCheck);
+  fopts << new BoolFilterOption(tfd.GPSFixes,  ui.GPSFixesCheck);
+  fopts << new BoolFilterOption(tfd.course, ui.courseCheck);
+  fopts << new BoolFilterOption(tfd.speed,  ui.speedCheck);
+
+  fopts << new IntSpinFilterOption(tfd.days,  ui.daysSpin, -2000, 2000);
+  fopts << new IntSpinFilterOption(tfd.hours, ui.hoursSpin);
+  fopts << new IntSpinFilterOption(tfd.mins,  ui.minsSpin);
+  fopts << new IntSpinFilterOption(tfd.secs,  ui.secsSpin);
+  fopts << new IntSpinFilterOption(tfd.splitTime,  ui.splitTimeSpin, 0, 1000);
+  fopts << new IntSpinFilterOption(tfd.splitDist,  ui.splitDistSpin, 0, 5280);
+
+  fopts << new DateTimeFilterOption(tfd.startTime, ui.startEdit);
+  fopts << new DateTimeFilterOption(tfd.stopTime,  ui.stopEdit);
+
+  fopts << new StringFilterOption(tfd.titleString, ui.titleText);
+  fopts << new ComboFilterOption(tfd.GPSFixesVal,  ui.GPSFixesCombo);
+  fopts << new ComboFilterOption(tfd.splitTimeUnit,  ui.splitTimeCombo);
+  fopts << new ComboFilterOption(tfd.splitDistUnit,  ui.splitDistCombo);
+  setWidgetValues();
+  checkChecks();
+}
+
+//------------------------------------------------------------------------
+void TrackWidget::otherCheckX()
+{
+  ui.TZCheck->setEnabled(ui.stopCheck->isChecked() || ui.startCheck->isChecked());
+
+  ui.splitTimeSpin->setEnabled(ui.splitTimeCheck->isChecked());
+  ui.splitTimeCombo->setEnabled(ui.splitTimeCheck->isChecked());
+  ui.splitDistSpin->setEnabled(ui.splitDistanceCheck->isChecked());
+  ui.splitDistCombo->setEnabled(ui.splitDistanceCheck->isChecked());
+  
+  bool bb = (ui.mergeCheck->isChecked() || ui.packCheck->isChecked());
+  ui.splitDateCheck->setEnabled(bb);
+  ui.splitTimeCheck->setEnabled(bb);
+  ui.splitDistanceCheck->setEnabled(bb);
+}
+
+//------------------------------------------------------------------------
+void TrackWidget::mergeCheckX()
+{
+  if (ui.mergeCheck->isChecked())
+    ui.packCheck->setChecked(false);
+  otherCheckX();
+}
+//------------------------------------------------------------------------
+void TrackWidget::packCheckX()
+{
+  if (ui.packCheck->isChecked())
+    ui.mergeCheck->setChecked(false);
+  otherCheckX();
+}
+
+//------------------------------------------------------------------------
+void TrackWidget::splitDateX()
+{
+  if (ui.splitDateCheck->isChecked()) {
+    ui.splitTimeCheck->setChecked(false);
+    ui.splitDistanceCheck->setChecked(false);
+  }
+  otherCheckX();
+}
+//------------------------------------------------------------------------
+void TrackWidget::splitTimeX()
+{
+  if (ui.splitTimeCheck->isChecked()) {
+    ui.splitDateCheck->setChecked(false);
+    ui.splitDistanceCheck->setChecked(false);
+  }
+  otherCheckX();
+}
+//------------------------------------------------------------------------
+void TrackWidget::splitDistanceX()
+{
+  if (ui.splitDistanceCheck->isChecked()) {
+    ui.splitDateCheck->setChecked(false);
+    ui.splitTimeCheck->setChecked(false);
+  }
+  otherCheckX();
+}
+
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+WayPtsWidget::WayPtsWidget(QWidget *parent, WayPtsFilterData &wfd): FilterWidget(parent) , wfd(wfd)
+{
+  ui.setupUi(this);
+  addCheckEnabler(ui.duplicatesCheck,
+                 QList<QWidget*>() << ui.shortNamesCheck << ui.locationsCheck);
+  addCheckEnabler(ui.positionCheck, 
+                 QList<QWidget*>() << ui.positionText << ui.positionUnitCombo);
+  addCheckEnabler(ui.radiusCheck,
+                 QList<QWidget*>() << ui.latLabel << ui.latText << ui.longLabel <<
+                 ui.longText << ui.radiusUnitCombo << ui.radiusText);
+
+  fopts << new BoolFilterOption(wfd.duplicates, ui.duplicatesCheck);
+  fopts << new BoolFilterOption(wfd.shortNames, ui.shortNamesCheck);
+  fopts << new BoolFilterOption(wfd.locations, ui.locationsCheck);
+  fopts << new BoolFilterOption(wfd.position, ui.positionCheck);
+  fopts << new BoolFilterOption(wfd.radius, ui.radiusCheck);
+  fopts << new BoolFilterOption(wfd.sort, ui.sortCheck);
+  fopts << new DoubleFilterOption(wfd.positionVal, ui.positionText, 0.0, 1.0E308);
+  fopts << new DoubleFilterOption(wfd.radiusVal, ui.radiusText, 0.0, 1.0E308);
+  fopts << new DoubleFilterOption(wfd.longVal, ui.longText, -180, 180, 7, 'f');
+  fopts << new DoubleFilterOption(wfd.latVal, ui.latText,  -90, 90, 7, 'f');
+  fopts << new ComboFilterOption(wfd.positionUnit, ui.positionUnitCombo);
+  fopts << new ComboFilterOption(wfd.radiusUnit, ui.radiusUnitCombo);
+
+  connect(ui.shortNamesCheck, SIGNAL(clicked()), this, SLOT(shortNamesCkX()));
+  connect(ui.locationsCheck, SIGNAL(clicked()), this, SLOT(locationsCkX()));
+  setWidgetValues();
+  checkChecks();
+}
+//------------------------------------------------------------------------
+void WayPtsWidget::shortNamesCkX()
+{
+  if (!ui.shortNamesCheck->isChecked())
+    ui.locationsCheck->setChecked(true);
+}
+//------------------------------------------------------------------------
+void WayPtsWidget::locationsCkX()
+{
+  if (!ui.locationsCheck->isChecked())
+    ui.shortNamesCheck->setChecked(true);
+}
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+RtTrkWidget::RtTrkWidget(QWidget *parent, RtTrkFilterData &rfd): FilterWidget(parent) , rfd(rfd)
+{
+  ui.setupUi(this);
+  addCheckEnabler(ui.simplifyCheck,
+                 QList<QWidget*>() << ui.limitToLabel << ui.limitToSpin << ui.pointLabel);
+
+  fopts << new BoolFilterOption(rfd.simplify, ui.simplifyCheck);
+  fopts << new BoolFilterOption(rfd.reverse, ui.reverseCheck);
+  fopts << new IntSpinFilterOption(rfd.limitTo, ui.limitToSpin, 1, 5000);
+  setWidgetValues();
+  checkChecks();
+}
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+MiscFltWidget::MiscFltWidget(QWidget *parent, MiscFltFilterData &mfd): FilterWidget(parent) , mfd(mfd)
+{
+  ui.setupUi(this);
+  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Tracks")).arg(QChar(8594)).arg(tr("Waypoints")));
+  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Routes")).arg(QChar(8594)).arg(tr("Tracks")));
+  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Waypoints")).arg(QChar(8594)).arg(tr("Routes")));
+  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Routes")).arg(QChar(8594)).arg(tr("Waypoints")));
+  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Tracks")).arg(QChar(8594)).arg(tr("Routes")));
+  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Waypoints")).arg(QChar(8594)).arg(tr("Tracks")));
+  addCheckEnabler(ui.transformCheck,
+                 QList<QWidget*>() << ui.transformCombo << ui.deleteCheck);
+
+  fopts << new BoolFilterOption(mfd.transform, ui.transformCheck);
+  fopts << new BoolFilterOption(mfd.swap, ui.swapCheck);
+  fopts << new BoolFilterOption(mfd.del, ui.deleteCheck);
+  fopts << new BoolFilterOption(mfd.nukeTracks, ui.nukeTracks);
+  fopts << new BoolFilterOption(mfd.nukeRoutes, ui.nukeRoutes);
+  fopts << new BoolFilterOption(mfd.nukeWaypoints, ui.nukeWaypoints);
+  fopts << new ComboFilterOption(mfd.transformVal,  ui.transformCombo);
+
+  setWidgetValues();
+  checkChecks();
+}
diff --git a/gpsbabel/gui/filterwidgets.cpp b/gpsbabel/gui/filterwidgets.cpp
deleted file mode 100644 (file)
index 09990ed..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-// -*- C++ -*-
-// $Id: filterwidgets.cpp,v 1.5 2009-11-02 20:38:02 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-
-#include "filterwidgets.h"
-
-
-//------------------------------------------------------------------------
-TrackWidget::TrackWidget(QWidget *parent, TrackFilterData &tfd): FilterWidget(parent) , tfd(tfd)
-{
-  ui.setupUi(this);
-
-  // Checkbox interlocks
-  addCheckEnabler(ui.titleCheck, ui.titleText);
-  addCheckEnabler(ui.moveCheck,
-                 (QList<QWidget *> ()
-                  << ui.daysLabel << ui.daysSpin
-                  << ui.hoursLabel<< ui.hoursSpin
-                  << ui.minsLabel << ui.minsSpin
-                  << ui.secsLabel << ui.secsSpin));
-  addCheckEnabler(ui.startCheck,    ui.startEdit);
-  addCheckEnabler(ui.stopCheck,     ui.stopEdit);
-  addCheckEnabler(ui.GPSFixesCheck, ui.GPSFixesCombo);
-
-  addCheckEnabler(ui.splitTimeCheck, 
-                 (QList<QWidget *> ()
-                  <<ui.splitTimeSpin
-                  <<ui.splitTimeCombo));
-  addCheckEnabler(ui.splitDistanceCheck, 
-                 (QList<QWidget *> ()
-                  <<ui.splitDistSpin
-                  <<ui.splitDistCombo));
-
-  connect(ui.mergeCheck, SIGNAL(clicked()) , this, SLOT(mergeCheckX()));
-  connect(ui.packCheck,  SIGNAL(clicked()),  this, SLOT(packCheckX()));
-  connect(ui.startCheck, SIGNAL(clicked()),  this, SLOT(otherCheckX()));
-  connect(ui.stopCheck,   SIGNAL(clicked()), this, SLOT(otherCheckX()));
-
-  connect(ui.splitDateCheck,   SIGNAL(clicked()), this, SLOT(splitDateX()));
-  connect(ui.splitTimeCheck,   SIGNAL(clicked()), this, SLOT(splitTimeX()));
-  connect(ui.splitDistanceCheck,   SIGNAL(clicked()), this, SLOT(splitDistanceX()));
-
-  ui.startEdit->setDisplayFormat("dd MMM yyyy hh:mm:ss AP");
-  ui.stopEdit->setDisplayFormat("dd MMM yyyy hh:mm:ss AP");
-
-  // Collect the data fields.
-  fopts << new BoolFilterOption(tfd.title,  ui.titleCheck);
-  fopts << new BoolFilterOption(tfd.move,   ui.moveCheck);
-  fopts << new BoolFilterOption(tfd.TZ,     ui.TZCheck);
-  fopts << new BoolFilterOption(tfd.start,  ui.startCheck);
-  fopts << new BoolFilterOption(tfd.stop,   ui.stopCheck);
-  fopts << new BoolFilterOption(tfd.pack,   ui.packCheck);
-  fopts << new BoolFilterOption(tfd.merge,  ui.mergeCheck);
-  fopts << new BoolFilterOption(tfd.splitByDate,  ui.splitDateCheck);
-  fopts << new BoolFilterOption(tfd.splitByTime,  ui.splitTimeCheck);
-  fopts << new BoolFilterOption(tfd.splitByDistance,  ui.splitDistanceCheck);
-  fopts << new BoolFilterOption(tfd.GPSFixes,  ui.GPSFixesCheck);
-  fopts << new BoolFilterOption(tfd.course, ui.courseCheck);
-  fopts << new BoolFilterOption(tfd.speed,  ui.speedCheck);
-
-  fopts << new IntSpinFilterOption(tfd.days,  ui.daysSpin, -2000, 2000);
-  fopts << new IntSpinFilterOption(tfd.hours, ui.hoursSpin);
-  fopts << new IntSpinFilterOption(tfd.mins,  ui.minsSpin);
-  fopts << new IntSpinFilterOption(tfd.secs,  ui.secsSpin);
-  fopts << new IntSpinFilterOption(tfd.splitTime,  ui.splitTimeSpin, 0, 1000);
-  fopts << new IntSpinFilterOption(tfd.splitDist,  ui.splitDistSpin, 0, 5280);
-
-  fopts << new DateTimeFilterOption(tfd.startTime, ui.startEdit);
-  fopts << new DateTimeFilterOption(tfd.stopTime,  ui.stopEdit);
-
-  fopts << new StringFilterOption(tfd.titleString, ui.titleText);
-  fopts << new ComboFilterOption(tfd.GPSFixesVal,  ui.GPSFixesCombo);
-  fopts << new ComboFilterOption(tfd.splitTimeUnit,  ui.splitTimeCombo);
-  fopts << new ComboFilterOption(tfd.splitDistUnit,  ui.splitDistCombo);
-  setWidgetValues();
-  checkChecks();
-}
-
-//------------------------------------------------------------------------
-void TrackWidget::otherCheckX()
-{
-  ui.TZCheck->setEnabled(ui.stopCheck->isChecked() || ui.startCheck->isChecked());
-
-  ui.splitTimeSpin->setEnabled(ui.splitTimeCheck->isChecked());
-  ui.splitTimeCombo->setEnabled(ui.splitTimeCheck->isChecked());
-  ui.splitDistSpin->setEnabled(ui.splitDistanceCheck->isChecked());
-  ui.splitDistCombo->setEnabled(ui.splitDistanceCheck->isChecked());
-  
-  bool bb = (ui.mergeCheck->isChecked() || ui.packCheck->isChecked());
-  ui.splitDateCheck->setEnabled(bb);
-  ui.splitTimeCheck->setEnabled(bb);
-  ui.splitDistanceCheck->setEnabled(bb);
-}
-
-//------------------------------------------------------------------------
-void TrackWidget::mergeCheckX()
-{
-  if (ui.mergeCheck->isChecked())
-    ui.packCheck->setChecked(false);
-  otherCheckX();
-}
-//------------------------------------------------------------------------
-void TrackWidget::packCheckX()
-{
-  if (ui.packCheck->isChecked())
-    ui.mergeCheck->setChecked(false);
-  otherCheckX();
-}
-
-//------------------------------------------------------------------------
-void TrackWidget::splitDateX()
-{
-  if (ui.splitDateCheck->isChecked()) {
-    ui.splitTimeCheck->setChecked(false);
-    ui.splitDistanceCheck->setChecked(false);
-  }
-  otherCheckX();
-}
-//------------------------------------------------------------------------
-void TrackWidget::splitTimeX()
-{
-  if (ui.splitTimeCheck->isChecked()) {
-    ui.splitDateCheck->setChecked(false);
-    ui.splitDistanceCheck->setChecked(false);
-  }
-  otherCheckX();
-}
-//------------------------------------------------------------------------
-void TrackWidget::splitDistanceX()
-{
-  if (ui.splitDistanceCheck->isChecked()) {
-    ui.splitDateCheck->setChecked(false);
-    ui.splitTimeCheck->setChecked(false);
-  }
-  otherCheckX();
-}
-
-
-//------------------------------------------------------------------------
-//------------------------------------------------------------------------
-WayPtsWidget::WayPtsWidget(QWidget *parent, WayPtsFilterData &wfd): FilterWidget(parent) , wfd(wfd)
-{
-  ui.setupUi(this);
-  addCheckEnabler(ui.duplicatesCheck,
-                 QList<QWidget*>() << ui.shortNamesCheck << ui.locationsCheck);
-  addCheckEnabler(ui.positionCheck, 
-                 QList<QWidget*>() << ui.positionText << ui.positionUnitCombo);
-  addCheckEnabler(ui.radiusCheck,
-                 QList<QWidget*>() << ui.latLabel << ui.latText << ui.longLabel <<
-                 ui.longText << ui.radiusUnitCombo << ui.radiusText);
-
-  fopts << new BoolFilterOption(wfd.duplicates, ui.duplicatesCheck);
-  fopts << new BoolFilterOption(wfd.shortNames, ui.shortNamesCheck);
-  fopts << new BoolFilterOption(wfd.locations, ui.locationsCheck);
-  fopts << new BoolFilterOption(wfd.position, ui.positionCheck);
-  fopts << new BoolFilterOption(wfd.radius, ui.radiusCheck);
-  fopts << new BoolFilterOption(wfd.sort, ui.sortCheck);
-  fopts << new DoubleFilterOption(wfd.positionVal, ui.positionText, 0.0, 1.0E308);
-  fopts << new DoubleFilterOption(wfd.radiusVal, ui.radiusText, 0.0, 1.0E308);
-  fopts << new DoubleFilterOption(wfd.longVal, ui.longText, -180, 180, 7, 'f');
-  fopts << new DoubleFilterOption(wfd.latVal, ui.latText,  -90, 90, 7, 'f');
-  fopts << new ComboFilterOption(wfd.positionUnit, ui.positionUnitCombo);
-  fopts << new ComboFilterOption(wfd.radiusUnit, ui.radiusUnitCombo);
-
-  connect(ui.shortNamesCheck, SIGNAL(clicked()), this, SLOT(shortNamesCkX()));
-  connect(ui.locationsCheck, SIGNAL(clicked()), this, SLOT(locationsCkX()));
-  setWidgetValues();
-  checkChecks();
-}
-//------------------------------------------------------------------------
-void WayPtsWidget::shortNamesCkX()
-{
-  if (!ui.shortNamesCheck->isChecked())
-    ui.locationsCheck->setChecked(true);
-}
-//------------------------------------------------------------------------
-void WayPtsWidget::locationsCkX()
-{
-  if (!ui.locationsCheck->isChecked())
-    ui.shortNamesCheck->setChecked(true);
-}
-
-//------------------------------------------------------------------------
-//------------------------------------------------------------------------
-RtTrkWidget::RtTrkWidget(QWidget *parent, RtTrkFilterData &rfd): FilterWidget(parent) , rfd(rfd)
-{
-  ui.setupUi(this);
-  addCheckEnabler(ui.simplifyCheck,
-                 QList<QWidget*>() << ui.limitToLabel << ui.limitToSpin << ui.pointLabel);
-
-  fopts << new BoolFilterOption(rfd.simplify, ui.simplifyCheck);
-  fopts << new BoolFilterOption(rfd.reverse, ui.reverseCheck);
-  fopts << new IntSpinFilterOption(rfd.limitTo, ui.limitToSpin, 1, 5000);
-  setWidgetValues();
-  checkChecks();
-}
-
-//------------------------------------------------------------------------
-//------------------------------------------------------------------------
-MiscFltWidget::MiscFltWidget(QWidget *parent, MiscFltFilterData &mfd): FilterWidget(parent) , mfd(mfd)
-{
-  ui.setupUi(this);
-  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Tracks")).arg(QChar(8594)).arg(tr("Waypoints")));
-  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Routes")).arg(QChar(8594)).arg(tr("Tracks")));
-  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Waypoints")).arg(QChar(8594)).arg(tr("Routes")));
-  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Routes")).arg(QChar(8594)).arg(tr("Waypoints")));
-  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Tracks")).arg(QChar(8594)).arg(tr("Routes")));
-  ui.transformCombo->addItem(QString("%1 %2 %3").arg(tr("Waypoints")).arg(QChar(8594)).arg(tr("Tracks")));
-  addCheckEnabler(ui.transformCheck,
-                 QList<QWidget*>() << ui.transformCombo << ui.deleteCheck);
-
-  fopts << new BoolFilterOption(mfd.transform, ui.transformCheck);
-  fopts << new BoolFilterOption(mfd.swap, ui.swapCheck);
-  fopts << new BoolFilterOption(mfd.del, ui.deleteCheck);
-  fopts << new BoolFilterOption(mfd.nukeTracks, ui.nukeTracks);
-  fopts << new BoolFilterOption(mfd.nukeRoutes, ui.nukeRoutes);
-  fopts << new BoolFilterOption(mfd.nukeWaypoints, ui.nukeWaypoints);
-  fopts << new ComboFilterOption(mfd.transformVal,  ui.transformCombo);
-
-  setWidgetValues();
-  checkChecks();
-}
diff --git a/gpsbabel/gui/format.cc b/gpsbabel/gui/format.cc
new file mode 100644 (file)
index 0000000..27b6f15
--- /dev/null
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+// $Id: format.cpp,v 1.4 2010-02-14 05:33:37 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#include "format.h"
+#include "mainwindow.h"
+
+QString Format::htmlBase = QString();
+
+static void saveOptions(QSettings &settings, const QString &prefix, const QList<FormatOption> &options) {
+  for (int i=0; i<options.size(); i++) {
+    QString kp = prefix + "." + options[i].getName();
+    QString k1 = kp + ".selected";
+    QString k2 = kp + ".value";
+    settings.setValue(k1, options[i].getSelected());
+    settings.setValue(k2, options[i].getValue());
+  }
+}
+
+static void restoreOptions(QSettings &settings, const QString&prefix, QList<FormatOption> &options) {
+  for (int i=0; i<options.size(); i++) {
+    QString kp = prefix + "." + options[i].getName();
+    QString k1 = kp + ".selected";
+    QString k2 = kp + ".value";
+    if (settings.contains(k1) && settings.contains(k2)) {
+      options[i].setSelected(settings.value(k1).toBool());
+      options[i].setValue(settings.value(k2));
+    }
+  }
+}
+
+void Format::saveSettings(QSettings &settings)
+{
+  saveOptions(settings, name+".input", inputOptions);
+  saveOptions(settings, name+".output", outputOptions);
+  settings.setValue(name + ".readcount", getReadUseCount());
+  settings.setValue(name + ".writecount", getWriteUseCount());
+  settings.setValue(name+".hidden", isHidden());
+}
+
+void Format::restoreSettings(QSettings &settings)
+{
+  restoreOptions(settings, name + ".input", inputOptions);
+  restoreOptions(settings, name + ".output", outputOptions);
+  bumpReadUseCount(settings.value(name + ".readcount").toInt());
+  bumpWriteUseCount(settings.value(name + ".writecount").toInt());
+  hidden_ = settings.value(name + ".hidden", false).toBool();
+}
+
+void Format::setToDefault()
+{
+  for (int i=0; i<inputOptions.size(); i++) {
+    inputOptions[i].setSelected(false);
+    inputOptions[i].setValue(QVariant());
+  }
+  for (int i=0; i<outputOptions.size(); i++) {
+    outputOptions[i].setSelected(false);
+    outputOptions[i].setValue(QVariant());
+  }
+}
diff --git a/gpsbabel/gui/format.cpp b/gpsbabel/gui/format.cpp
deleted file mode 100644 (file)
index 27b6f15..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// -*- C++ -*-
-// $Id: format.cpp,v 1.4 2010-02-14 05:33:37 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#include "format.h"
-#include "mainwindow.h"
-
-QString Format::htmlBase = QString();
-
-static void saveOptions(QSettings &settings, const QString &prefix, const QList<FormatOption> &options) {
-  for (int i=0; i<options.size(); i++) {
-    QString kp = prefix + "." + options[i].getName();
-    QString k1 = kp + ".selected";
-    QString k2 = kp + ".value";
-    settings.setValue(k1, options[i].getSelected());
-    settings.setValue(k2, options[i].getValue());
-  }
-}
-
-static void restoreOptions(QSettings &settings, const QString&prefix, QList<FormatOption> &options) {
-  for (int i=0; i<options.size(); i++) {
-    QString kp = prefix + "." + options[i].getName();
-    QString k1 = kp + ".selected";
-    QString k2 = kp + ".value";
-    if (settings.contains(k1) && settings.contains(k2)) {
-      options[i].setSelected(settings.value(k1).toBool());
-      options[i].setValue(settings.value(k2));
-    }
-  }
-}
-
-void Format::saveSettings(QSettings &settings)
-{
-  saveOptions(settings, name+".input", inputOptions);
-  saveOptions(settings, name+".output", outputOptions);
-  settings.setValue(name + ".readcount", getReadUseCount());
-  settings.setValue(name + ".writecount", getWriteUseCount());
-  settings.setValue(name+".hidden", isHidden());
-}
-
-void Format::restoreSettings(QSettings &settings)
-{
-  restoreOptions(settings, name + ".input", inputOptions);
-  restoreOptions(settings, name + ".output", outputOptions);
-  bumpReadUseCount(settings.value(name + ".readcount").toInt());
-  bumpWriteUseCount(settings.value(name + ".writecount").toInt());
-  hidden_ = settings.value(name + ".hidden", false).toBool();
-}
-
-void Format::setToDefault()
-{
-  for (int i=0; i<inputOptions.size(); i++) {
-    inputOptions[i].setSelected(false);
-    inputOptions[i].setValue(QVariant());
-  }
-  for (int i=0; i<outputOptions.size(); i++) {
-    outputOptions[i].setSelected(false);
-    outputOptions[i].setValue(QVariant());
-  }
-}
diff --git a/gpsbabel/gui/formatload.cc b/gpsbabel/gui/formatload.cc
new file mode 100644 (file)
index 0000000..3ca039e
--- /dev/null
@@ -0,0 +1,162 @@
+// -*- c++ -*-
+// $Id: formatload.cpp,v 1.3 2009-11-02 20:38:02 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+
+#include <QProcess>
+#include <QMessageBox>
+#include <QTextStream>
+#include <QCoreApplication>
+#include <QApplication>
+#include "formatload.h"
+#include "appname.h"
+
+//------------------------------------------------------------------------
+static QString xlt(const QString &f) {
+  return QCoreApplication::translate("", f.toStdString().c_str());
+}
+
+//------------------------------------------------------------------------
+bool FormatLoad::skipToValidLine()
+{
+  QRegExp regex("^(file|serial)");
+  while (currentLine <lines.size() && regex.indexIn(lines[currentLine]) != 0)
+    currentLine++;
+  return (currentLine<lines.size());
+}
+
+//------------------------------------------------------------------------
+bool FormatLoad::processFormat(Format &format)
+{
+  QStringList hfields = lines[currentLine++].split("\t");
+  if (hfields.size() < 5) {
+    return false;
+  }
+  QString htmlPage = lines[currentLine++];
+  htmlPage.replace(QRegExp("^[\\s]*"), "");
+  htmlPage.replace(QRegExp("[\\s]$"), "");
+
+  QRegExp regex("^option");
+  QList <FormatOption> optionList;
+  while (currentLine <lines.size() && regex.indexIn(lines[currentLine]) == 0) {
+    QStringList ofields = lines[currentLine].split("\t");
+    if (ofields.size() < 9) {
+      return false;
+    }
+    QString name        = ofields[2];
+    QString description = ofields[3];
+    QString optionType  = ofields[4];
+    QString optionDef   = ofields[5];
+    QString optionMin   = ofields[6];
+    QString optionMax   = ofields[7];
+    QString optionHtml  = ofields[8];
+    FormatOption::optionType type = FormatOption::OPTbool;
+    if (optionType == "boolean")
+      type = FormatOption::OPTbool;
+    else if (optionType == "string")
+      type = FormatOption::OPTstring;
+    else if (optionType == "integer") {
+      type = (optionMax != "" && optionMin != "") ? FormatOption::OPTboundedInt : FormatOption::OPTint;
+      if (optionMax == "")
+       optionMax = "2147483647";
+      if (optionMin == "")
+       optionMin = "-2147483647";
+    }
+    else if (optionType == "float") {
+      type = FormatOption::OPTfloat;
+      if (optionMax == "")
+       optionMax = "1.0E308";
+      if (optionMin == "")
+       optionMin = "-1.0E308";
+    }
+    else if (optionType == "file") {
+      type = FormatOption::OPTinFile;
+    }
+    else if (optionType == "outfile") {
+      type = FormatOption::OPToutFile;
+    }
+    else {
+      type = FormatOption::OPTstring;
+    }
+    optionList << FormatOption(name, xlt(description),
+                              type, QVariant(optionDef), QVariant(optionMin),
+                              QVariant(optionMax), optionHtml);
+    currentLine++;
+  }
+  QList <FormatOption> optionList2 = optionList;
+
+  format = Format(hfields[2], xlt(hfields[4]),
+                 hfields[1][0] == QChar('r'),  hfields[1][2] == QChar('r'),  hfields[1][4] == QChar('r'),
+                 hfields[1][1] == QChar('w'),  hfields[1][3] == QChar('w'),  hfields[1][5] == QChar('w'),
+                 hfields[0] == "file",
+                 hfields[0] == "serial",
+                 QStringList() << hfields[3],
+                 optionList,
+                 optionList2, htmlPage);
+  if (htmlPage.length() > 0 && Format::getHtmlBase().length() == 0) {
+    QString base = htmlPage;
+    base.replace(QRegExp("/[^/]+$"), "/");
+    Format::setHtmlBase(base);
+  }
+  return true;
+}
+
+//------------------------------------------------------------------------
+bool FormatLoad::getFormats(QList<Format> &formatList)
+{
+  formatList.clear();
+
+  QProcess babel;
+  babel.start("gpsbabel", QStringList() << "-^3");
+  if (!babel.waitForStarted())
+    return false;
+  babel.closeWriteChannel();
+  if (!babel.waitForFinished())
+    return false;
+  if (babel.exitCode() != 0)
+    return false;
+
+  QTextStream tstream(babel.readAll());
+  QList<int>lineList;
+  int k=0;
+  while(!tstream.atEnd()) {
+    QString l = tstream.readLine();
+    k++;
+    if (!QRegExp("^[\\s]*$").exactMatch(l)) {
+      lines << l;
+      lineList<<k;
+    }
+  }
+  currentLine = 0;
+
+  for  (bool dataPresent = skipToValidLine(); dataPresent; dataPresent=skipToValidLine()) {
+    Format format;
+    if (!processFormat(format)) {
+      QMessageBox::information
+       (0, appName,
+        QObject::tr("Error processing formats from running process \"gpsbabel -^3\" at line %1").arg(lineList[currentLine]));
+    }
+    else {
+      formatList << format;
+    }
+  }
+  return true;
+}
diff --git a/gpsbabel/gui/formatload.cpp b/gpsbabel/gui/formatload.cpp
deleted file mode 100644 (file)
index 3ca039e..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-// -*- c++ -*-
-// $Id: formatload.cpp,v 1.3 2009-11-02 20:38:02 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-
-#include <QProcess>
-#include <QMessageBox>
-#include <QTextStream>
-#include <QCoreApplication>
-#include <QApplication>
-#include "formatload.h"
-#include "appname.h"
-
-//------------------------------------------------------------------------
-static QString xlt(const QString &f) {
-  return QCoreApplication::translate("", f.toStdString().c_str());
-}
-
-//------------------------------------------------------------------------
-bool FormatLoad::skipToValidLine()
-{
-  QRegExp regex("^(file|serial)");
-  while (currentLine <lines.size() && regex.indexIn(lines[currentLine]) != 0)
-    currentLine++;
-  return (currentLine<lines.size());
-}
-
-//------------------------------------------------------------------------
-bool FormatLoad::processFormat(Format &format)
-{
-  QStringList hfields = lines[currentLine++].split("\t");
-  if (hfields.size() < 5) {
-    return false;
-  }
-  QString htmlPage = lines[currentLine++];
-  htmlPage.replace(QRegExp("^[\\s]*"), "");
-  htmlPage.replace(QRegExp("[\\s]$"), "");
-
-  QRegExp regex("^option");
-  QList <FormatOption> optionList;
-  while (currentLine <lines.size() && regex.indexIn(lines[currentLine]) == 0) {
-    QStringList ofields = lines[currentLine].split("\t");
-    if (ofields.size() < 9) {
-      return false;
-    }
-    QString name        = ofields[2];
-    QString description = ofields[3];
-    QString optionType  = ofields[4];
-    QString optionDef   = ofields[5];
-    QString optionMin   = ofields[6];
-    QString optionMax   = ofields[7];
-    QString optionHtml  = ofields[8];
-    FormatOption::optionType type = FormatOption::OPTbool;
-    if (optionType == "boolean")
-      type = FormatOption::OPTbool;
-    else if (optionType == "string")
-      type = FormatOption::OPTstring;
-    else if (optionType == "integer") {
-      type = (optionMax != "" && optionMin != "") ? FormatOption::OPTboundedInt : FormatOption::OPTint;
-      if (optionMax == "")
-       optionMax = "2147483647";
-      if (optionMin == "")
-       optionMin = "-2147483647";
-    }
-    else if (optionType == "float") {
-      type = FormatOption::OPTfloat;
-      if (optionMax == "")
-       optionMax = "1.0E308";
-      if (optionMin == "")
-       optionMin = "-1.0E308";
-    }
-    else if (optionType == "file") {
-      type = FormatOption::OPTinFile;
-    }
-    else if (optionType == "outfile") {
-      type = FormatOption::OPToutFile;
-    }
-    else {
-      type = FormatOption::OPTstring;
-    }
-    optionList << FormatOption(name, xlt(description),
-                              type, QVariant(optionDef), QVariant(optionMin),
-                              QVariant(optionMax), optionHtml);
-    currentLine++;
-  }
-  QList <FormatOption> optionList2 = optionList;
-
-  format = Format(hfields[2], xlt(hfields[4]),
-                 hfields[1][0] == QChar('r'),  hfields[1][2] == QChar('r'),  hfields[1][4] == QChar('r'),
-                 hfields[1][1] == QChar('w'),  hfields[1][3] == QChar('w'),  hfields[1][5] == QChar('w'),
-                 hfields[0] == "file",
-                 hfields[0] == "serial",
-                 QStringList() << hfields[3],
-                 optionList,
-                 optionList2, htmlPage);
-  if (htmlPage.length() > 0 && Format::getHtmlBase().length() == 0) {
-    QString base = htmlPage;
-    base.replace(QRegExp("/[^/]+$"), "/");
-    Format::setHtmlBase(base);
-  }
-  return true;
-}
-
-//------------------------------------------------------------------------
-bool FormatLoad::getFormats(QList<Format> &formatList)
-{
-  formatList.clear();
-
-  QProcess babel;
-  babel.start("gpsbabel", QStringList() << "-^3");
-  if (!babel.waitForStarted())
-    return false;
-  babel.closeWriteChannel();
-  if (!babel.waitForFinished())
-    return false;
-  if (babel.exitCode() != 0)
-    return false;
-
-  QTextStream tstream(babel.readAll());
-  QList<int>lineList;
-  int k=0;
-  while(!tstream.atEnd()) {
-    QString l = tstream.readLine();
-    k++;
-    if (!QRegExp("^[\\s]*$").exactMatch(l)) {
-      lines << l;
-      lineList<<k;
-    }
-  }
-  currentLine = 0;
-
-  for  (bool dataPresent = skipToValidLine(); dataPresent; dataPresent=skipToValidLine()) {
-    Format format;
-    if (!processFormat(format)) {
-      QMessageBox::information
-       (0, appName,
-        QObject::tr("Error processing formats from running process \"gpsbabel -^3\" at line %1").arg(lineList[currentLine]));
-    }
-    else {
-      formatList << format;
-    }
-  }
-  return true;
-}
diff --git a/gpsbabel/gui/gmapdlg.cc b/gpsbabel/gui/gmapdlg.cc
new file mode 100644 (file)
index 0000000..d8105a1
--- /dev/null
@@ -0,0 +1,567 @@
+// -*- C++ -*-
+// $Id: gmapdlg.cpp,v 1.3 2009-11-02 20:38:02 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+
+#include <QStandardItemModel>
+#include <QMenu>
+#include <QHeaderView>
+#include "gmapdlg.h"
+#include "appname.h"
+#include "gpx.h"
+
+//------------------------------------------------------------------------
+class StandardItem: public QStandardItem
+{
+ public:
+  StandardItem(const QString &text): QStandardItem(text)
+    {
+      this->setEditable(false);
+    }
+};
+
+//------------------------------------------------------------------------
+class TreeAction: public QAction
+{
+public:
+  TreeAction(const QString &text,
+            QObject *obj, const char *member,  QObject *parent): QAction(text, parent)
+  {
+    connect(this, SIGNAL(triggered()), obj, member);
+  }
+};
+//------------------------------------------------------------------------
+QString GMapDialog::formatLength(double l)
+{
+  double metricLength = l;
+  QString metricUnit = tr("meters");
+  int metricPrecision = 2;
+  if (l > 1000.0) {
+    metricLength = l/1000.0;
+    metricUnit = "km";
+    metricPrecision = 3;
+  }
+
+  double fpsLength = l*1000.0/25.4/12.0;
+  QString fpsUnit = tr("feet");
+  int fpsPrecision = 1;
+  if (fpsLength >5280.0) {
+    fpsLength /= 5280.0;
+    fpsUnit = tr("miles");
+    fpsPrecision = 3;
+  }
+  return QString(tr("Length: %1 %2\n  %3 %4")
+                .arg(metricLength, 0, 'f', metricPrecision)
+                .arg(metricUnit)
+                .arg(fpsLength, 0, 'f', fpsPrecision)
+                .arg(fpsUnit));
+
+}
+//------------------------------------------------------------------------
+void GMapDialog::appendWaypointInfo(QStandardItem *it, const GpxWaypoint &wpt)
+{
+  it->appendRow(new StandardItem(tr("Lat: %1").arg(wpt.getLocation().lat(), 0, 'f', 7)));
+  it->appendRow(new StandardItem(tr("Lng: %1").arg(wpt.getLocation().lng(), 0, 'f', 7)));
+  if (wpt.getDescription() != QString())
+    it->appendRow(new StandardItem(tr("Desc: %1").arg(wpt.getDescription())));
+  if (wpt.getComment() != QString() && wpt.getComment() != wpt.getDescription())
+    it->appendRow(new StandardItem(tr("Cmt: %1").arg(wpt.getComment())));
+  if (wpt.getElevation() > -50000)
+    it->appendRow(new StandardItem(tr("Ele: %1").arg(wpt.getElevation())));
+
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::appendTrackInfo(QStandardItem *it, const GpxTrack &trk)
+{
+  QDateTime startTime, stopTime;
+  bool first = true;
+  int count = 0;
+  foreach (const GpxTrackSegment &seg, trk.getTrackSegments()) {
+    foreach (const GpxTrackPoint &pt, seg.getTrackPoints()) {
+      count++;
+      QDateTime t = pt.getDateTime();
+      if (!t.isValid())
+       continue;
+      if (first) {
+       startTime = t;
+       stopTime = t;
+       first = false;
+      }
+      else {
+       if (t < startTime)
+         startTime = t;
+       if (t > stopTime)
+         stopTime = t;
+      }
+    }
+  }
+  if (startTime.isValid()) {
+    it->appendRow(new StandardItem(tr("Start: %1")
+                                   .arg(startTime.toString("yyyy-MMM-dd HH:mm:ss"))));
+    it->appendRow(new StandardItem(tr("Stop: %1")
+                                   .arg(stopTime.toString("yyyy-MMM-dd HH:mm:ss"))));
+  }
+  it->appendRow(new StandardItem(tr("Points: %1").arg(count)));
+
+  it->appendRow(new StandardItem(formatLength(trk.length())));
+
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::appendRouteInfo(QStandardItem *it, const GpxRoute &rte)
+{
+  it->appendRow(new StandardItem(formatLength(rte.length())));
+}
+
+//------------------------------------------------------------------------
+GMapDialog::GMapDialog(QWidget *parent, const QString &gpxFileName, QPlainTextEdit *te): QDialog(parent)
+{
+  ui.setupUi(this);
+  this->setWindowTitle(QString(appName) + " " + QString("Google Maps"));
+  gpx.read(gpxFileName);
+
+  mapWidget = new Map(this, gpx, te);
+  QHBoxLayout *lay = new QHBoxLayout(ui.frame);
+  lay->setContentsMargins(0, 0, 0, 0);
+  lay->addWidget(mapWidget);
+
+  model = new QStandardItemModel(this);
+
+  wptItem = new StandardItem(tr("Waypoints"));
+  wptItem->setCheckable(true);
+  wptItem->setCheckState(Qt::Checked);
+  model->appendRow(wptItem);
+  for (int i=0; i<gpx.getWaypoints().size(); i++) {
+    GpxWaypoint &wpt = gpx.getWaypoints()[i];
+    QStandardItem *it = new StandardItem(wpt.getName());
+    wptItem->appendRow(it);
+    it->setCheckable(true);
+    it->setCheckState(Qt::Checked);
+    it->setData(qVariantFromValue((void *)&wpt));
+    appendWaypointInfo(it, wpt);
+    wptList << it;
+  }
+
+  trkItem = new StandardItem(tr("Tracks"));
+  trkItem->setCheckable(true);
+  trkItem->setCheckState(Qt::Checked);
+  model->appendRow(trkItem);
+  for (int i=0; i<gpx.getTracks().size(); i++) {
+    GpxTrack &trk = gpx.getTracks()[i];
+    QStandardItem *it = new StandardItem(trk.getName());
+    trkItem->appendRow(it);
+    it->setCheckable(true);
+    it->setCheckState(Qt::Checked);
+    it->setData(qVariantFromValue((void *)&trk));
+    appendTrackInfo(it, trk);
+    trkList << it;
+  }
+
+  rteItem = new StandardItem(tr("Routes"));
+  rteItem->setCheckable(true);
+  rteItem->setCheckState(Qt::Checked);
+  model->appendRow(rteItem);
+  for (int i=0; i<gpx.getRoutes().size(); i++) {
+    GpxRoute &rte = gpx.getRoutes()[i];
+    QStandardItem *it = new StandardItem(rte.getName());
+    rteItem->appendRow(it);
+    it->setCheckable(true);
+    it->setCheckState(Qt::Checked);
+    it->setData(qVariantFromValue((void *)&rte));
+    appendRouteInfo(it, rte);
+    rteList << it;
+  }
+
+  ui.treeView->header()->hide();
+  ui.treeView->setModel(model);
+  ui.treeView->setExpandsOnDoubleClick(false);
+  connect(model, SIGNAL(itemChanged(QStandardItem *)),
+         this,  SLOT(itemChangedX(QStandardItem *)));
+  connect(mapWidget, SIGNAL(waypointClicked(int)), this, SLOT(waypointClickedX(int)));
+  connect(mapWidget, SIGNAL(routeClicked(int)), this, SLOT(routeClickedX(int)));
+  connect(mapWidget, SIGNAL(trackClicked(int)), this, SLOT(trackClickedX(int)));
+  connect(ui.treeView, SIGNAL(doubleClicked(const QModelIndex &)),
+         this, SLOT(treeDoubleClicked(const QModelIndex&)));
+  connect(ui.treeView->selectionModel(), SIGNAL(selectionChanged (const QItemSelection &,  const QItemSelection &)),
+         this, SLOT(selectionChangedX(const QItemSelection &,  const QItemSelection &)));
+                                               
+  ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+  connect(ui.treeView, SIGNAL(customContextMenuRequested(const QPoint &)),
+         this, SLOT(showContextMenu(const QPoint &)));
+
+  connect(ui.copyButton, SIGNAL(clicked()), this, SLOT(copyButtonClickedX()));
+
+  ui.copyButton->hide(); // Hide for now, not working
+
+}
+
+//-------------------------------------------------------------------------
+void GMapDialog::itemChangedX(QStandardItem *it)
+{
+  bool show = (it->checkState() == Qt::Checked);
+  if (it == trkItem) {
+    if (show)
+      mapWidget->showTracks(gpx.getTracks());
+    else
+      mapWidget->hideAllTracks();
+  }
+
+  else if (it == wptItem) {
+    if (show)
+      mapWidget->showWaypoints(gpx.getWaypoints());
+    else
+      mapWidget->hideAllWaypoints();
+  }
+
+  else if (it == rteItem) {
+    if (show)
+      mapWidget->showRoutes(gpx.getRoutes());
+    else
+      mapWidget->hideAllRoutes();
+  }
+
+  else {
+    // Individual items, find the right one.
+    GpxItem *git = static_cast<GpxItem *>(it->data().value<void *>());
+    if (git != 0) {
+      git->setVisible(show);
+      for (int i=0; i<gpx.getWaypoints().size(); i++) {
+       if (&gpx.getWaypoints()[i] == git) {
+         mapWidget->setWaypointVisibility(i, show);
+       }
+      }
+      for (int i=0; i<gpx.getTracks().size(); i++) {
+       if (&gpx.getTracks()[i] == git) {
+         mapWidget->setTrackVisibility(i, show);
+       }
+      }
+      for (int i=0; i<gpx.getRoutes().size(); i++) {
+       if (&gpx.getRoutes()[i] == git) {
+         mapWidget->setRouteVisibility(i, show);
+       }
+      }
+    }
+  }
+}
+
+//-------------------------------------------------------------------------
+int GMapDialog::waypointIndex(QStandardItem *it)
+{
+  for (int j=0; j<wptList.size(); j++){
+    if (it == wptList[j])
+      return j;
+  }
+  return -1;
+}
+
+//-------------------------------------------------------------------------
+int GMapDialog::trackIndex(QStandardItem *it)
+{
+  for (int j=0; j<trkList.size(); j++){
+    if (it == trkList[j])
+      return j;
+  }
+  return -1;
+}
+
+//-------------------------------------------------------------------------
+int GMapDialog::routeIndex(QStandardItem *it)
+{
+  for (int j=0; j<rteList.size(); j++){
+    if (it == rteList[j])
+      return j;
+  }
+  return -1;
+}
+
+//-------------------------------------------------------------------------
+void GMapDialog::treeDoubleClicked(const QModelIndex &idx)
+{
+  QStandardItem *it = model->itemFromIndex(idx);
+  int i = waypointIndex(it);
+  if (i >= 0) {
+    it->setCheckState(Qt::Checked);
+    gpx.getWaypoints()[i].setVisible(true);
+    mapWidget->panTo(gpx.getWaypoints()[i].getLocation());
+    mapWidget->setWaypointVisibility(i, true);
+    return;
+  }
+  i = trackIndex(it);
+  if (i >= 0) {
+    mapWidget->frameTrack(i);
+    it->setCheckState(Qt::Checked);
+    gpx.getTracks()[i].setVisible(true);
+    mapWidget->setTrackVisibility(i, true);
+    return;
+  }
+  i = routeIndex(it);
+  if (i >= 0) {
+    mapWidget->frameRoute(i);
+    it->setCheckState(Qt::Checked);
+    gpx.getRoutes()[i].setVisible(true);
+    mapWidget->setRouteVisibility(i, true);
+    return;
+  }
+}
+
+//-------------------------------------------------------------------------
+void GMapDialog::waypointClickedX(int i)
+{
+  if (i>=0 && i < wptList.size()) {
+    QStandardItem *it = wptList[i];
+    QModelIndex idx = model->indexFromItem(it);
+    ui.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
+    ui.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+  }
+}
+//-------------------------------------------------------------------------
+void GMapDialog::trackClickedX(int i)
+{
+  if (i>=0 && i <trkList.size()) {
+    QStandardItem *it = trkList[i];
+    QModelIndex idx = model->indexFromItem(it);
+    ui.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
+    ui.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+  }
+}
+
+//-------------------------------------------------------------------------
+void GMapDialog::routeClickedX(int i)
+{
+  if (i>=0 && i <rteList.size()) {
+    QStandardItem *it = rteList[i];
+    QModelIndex idx = model->indexFromItem(it);
+    ui.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
+    ui.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+  }
+}
+
+//-------------------------------------------------------------------------
+void GMapDialog::selectionChangedX (const QItemSelection &sel,  const QItemSelection &desel)
+{
+  int k=0;
+  foreach (QStandardItem*w, wptList) {
+    QModelIndex idx = model->indexFromItem(w);
+    if (desel.contains(idx))
+      mapWidget->setWaypointColorBlue(k);
+    if (sel.contains(idx))
+      mapWidget->setWaypointColorRed(k);
+    k++;
+  }
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::expandCollapseAll(const QList<QStandardItem *> &li,
+                                  QStandardItem *top, bool exp)
+{
+  ui.treeView->setExpanded(model->indexFromItem(top), exp);
+  foreach (QStandardItem*it, li) {
+    QModelIndex idx = model->indexFromItem(it);
+    ui.treeView->setExpanded(idx, exp);
+  }
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::expandAllWaypoints()
+{
+  expandCollapseAll(wptList, wptItem, true);
+}
+//------------------------------------------------------------------------
+void GMapDialog::expandAllTracks()
+{
+  expandCollapseAll(trkList, trkItem, true);
+}
+//------------------------------------------------------------------------
+void GMapDialog::expandAllRoutes()
+{
+  expandCollapseAll(rteList, rteItem, true);
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::collapseAllWaypoints()
+{
+  expandCollapseAll(wptList, wptItem,false);
+}
+//------------------------------------------------------------------------
+void GMapDialog::collapseAllTracks()
+{
+  expandCollapseAll(trkList, trkItem,false);
+}
+//------------------------------------------------------------------------
+void GMapDialog::collapseAllRoutes()
+{
+  expandCollapseAll(rteList, rteItem,false);
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::checkUncheckAll(const QList<QStandardItem *> &li,
+                                  QStandardItem *top, bool ck)
+{
+  top->setCheckState(ck ? Qt::Checked: Qt::Unchecked);
+  foreach (QStandardItem*it, li) {
+    it->setCheckState(ck ? Qt::Checked: Qt::Unchecked);
+  }
+}
+//------------------------------------------------------------------------
+void GMapDialog::showAllWaypoints()
+{
+  foreach (GpxWaypoint wpt, gpx.getWaypoints())
+    wpt.setVisible(true);
+  checkUncheckAll(wptList, wptItem, true);
+  mapWidget->showWaypoints(gpx.getWaypoints());
+}
+//------------------------------------------------------------------------
+void GMapDialog::showAllTracks()
+{
+  foreach (GpxTrack trk, gpx.getTracks())
+    trk.setVisible(true);
+  checkUncheckAll(trkList, trkItem, true);
+  mapWidget->showTracks(gpx.getTracks());
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::showAllRoutes()
+{
+  foreach (GpxRoute rte, gpx.getRoutes())
+    rte.setVisible(true);
+  checkUncheckAll(rteList, rteItem, true);
+  mapWidget->showRoutes(gpx.getRoutes());
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::hideAllWaypoints()
+{
+  foreach (GpxWaypoint wpt, gpx.getWaypoints())
+    wpt.setVisible(false);
+  checkUncheckAll(wptList, wptItem, false);
+  mapWidget->showWaypoints(gpx.getWaypoints());
+}
+//------------------------------------------------------------------------
+void GMapDialog::hideAllTracks()
+{
+  foreach (GpxTrack trk, gpx.getTracks())
+    trk.setVisible(false);
+  checkUncheckAll(trkList, trkItem, false);
+  mapWidget->showTracks(gpx.getTracks());
+
+}
+//------------------------------------------------------------------------
+void GMapDialog::hideAllRoutes()
+{
+  foreach (GpxRoute rte, gpx.getRoutes())
+    rte.setVisible(false);
+  checkUncheckAll(rteList, rteItem, false);
+  mapWidget->showRoutes(gpx.getRoutes());
+
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::showOnlyThisWaypoint()
+{
+  QList <GpxWaypoint> &tlist = gpx.getWaypoints();
+  for (int i=0; i<tlist.size(); i++) {
+    tlist[i].setVisible(i == menuIndex? true: false);
+    trkList[i]->setCheckState(i==menuIndex? Qt::Checked: Qt::Unchecked);
+  }
+  wptItem->setCheckState(Qt::Checked);
+  mapWidget->showWaypoints(gpx.getWaypoints());
+}
+//------------------------------------------------------------------------
+void GMapDialog::showOnlyThisTrack()
+{
+  QList <GpxTrack> &tlist = gpx.getTracks();
+  for (int i=0; i<tlist.size(); i++) {
+    tlist[i].setVisible(i == menuIndex? true: false);
+    trkList[i]->setCheckState(i==menuIndex? Qt::Checked: Qt::Unchecked);
+  }
+  trkItem->setCheckState(Qt::Checked);
+  mapWidget->showTracks(gpx.getTracks());
+
+}
+//------------------------------------------------------------------------
+void GMapDialog::showOnlyThisRoute()
+{
+  QList <GpxRoute> &rlist = gpx.getRoutes();
+  for (int i=0; i<rlist.size(); i++) {
+    rlist[i].setVisible(i == menuIndex? true: false);
+    rteList[i]->setCheckState(i==menuIndex? Qt::Checked: Qt::Unchecked);
+  }
+  rteItem->setCheckState(Qt::Checked);
+  mapWidget->showRoutes(gpx.getRoutes());
+
+}
+
+//------------------------------------------------------------------------
+void GMapDialog::showContextMenu(const QPoint &pt)
+{
+  QModelIndex idx = ui.treeView->indexAt(pt);
+  QStandardItem *it = model->itemFromIndex(idx);
+  int j;
+  if (model->indexFromItem(wptItem) == idx) {
+    QMenu menu(this);
+    menu.addAction(new TreeAction(tr("Show All Waypoints"), this, SLOT(showAllWaypoints()), &menu));
+    menu.addAction(new TreeAction(tr("Hide All Waypoints"), this, SLOT(hideAllWaypoints()),&menu));
+    menu.addAction(new TreeAction(tr("Expand All"), this, SLOT(expandAllWaypoints()),&menu));
+    menu.addAction(new TreeAction(tr("Collapse All"), this, SLOT(collapseAllWaypoints()),&menu));
+    menu.exec(ui.treeView->mapToGlobal(pt));
+  }
+  else if (model->indexFromItem(rteItem) == idx) {
+    QMenu menu(this);
+    menu.addAction(new TreeAction(tr("Show All Routes"), this, SLOT(showAllRoutes()), &menu));
+    menu.addAction(new TreeAction(tr("Hide All Routes"), this, SLOT(hideAllRoutes()),&menu));
+    menu.addAction(new TreeAction(tr("Expand All"), this, SLOT(expandAllRoutes()),&menu));
+    menu.addAction(new TreeAction(tr("Collapse All"), this, SLOT(collapseAllRoutes()),&menu));
+    menu.exec(ui.treeView->mapToGlobal(pt));
+  }
+  else if (model->indexFromItem(trkItem) == idx) {
+    QMenu menu(this);
+    menu.addAction(new TreeAction(tr("Show All Tracks"), this, SLOT(showAllTracks()), &menu));
+    menu.addAction(new TreeAction(tr("Hide All Tracks"), this, SLOT(hideAllTracks()),&menu));
+    menu.addAction(new TreeAction(tr("Expand All"), this, SLOT(expandAllTracks()),&menu));
+    menu.addAction(new TreeAction(tr("Collapse All"), this, SLOT(collapseAllTracks()),&menu));
+    menu.exec(ui.treeView->mapToGlobal(pt));
+  }
+  else if ((j = waypointIndex(it)) >=0) {
+    QMenu menu(this);
+    menu.addAction(new TreeAction(tr("Show Only This Waypoint"), this, SLOT(showOnlyThisWaypoint()), &menu));
+    menuIndex = j;
+    menu.exec(ui.treeView->mapToGlobal(pt));
+  }
+  else if ((j = trackIndex(it)) >=0) {
+    QMenu menu(this);
+    menu.addAction(new TreeAction(tr("Show Only This Track"), this, SLOT(showOnlyThisTrack()), &menu));
+    menuIndex = j;
+    menu.exec(ui.treeView->mapToGlobal(pt));
+  }
+  else if ((j = routeIndex(it)) >=0) {
+    QMenu menu(this);
+    menu.addAction(new TreeAction(tr("Show Only This Route"), this, SLOT(showOnlyThisRoute()), &menu));
+    menuIndex = j;
+    menu.exec(ui.treeView->mapToGlobal(pt));
+  }
+  else {
+  }
+}
+//------------------------------------------------------------------------
+void GMapDialog::copyButtonClickedX() {
+  
+}
diff --git a/gpsbabel/gui/gmapdlg.cpp b/gpsbabel/gui/gmapdlg.cpp
deleted file mode 100644 (file)
index d8105a1..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-// -*- C++ -*-
-// $Id: gmapdlg.cpp,v 1.3 2009-11-02 20:38:02 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-
-#include <QStandardItemModel>
-#include <QMenu>
-#include <QHeaderView>
-#include "gmapdlg.h"
-#include "appname.h"
-#include "gpx.h"
-
-//------------------------------------------------------------------------
-class StandardItem: public QStandardItem
-{
- public:
-  StandardItem(const QString &text): QStandardItem(text)
-    {
-      this->setEditable(false);
-    }
-};
-
-//------------------------------------------------------------------------
-class TreeAction: public QAction
-{
-public:
-  TreeAction(const QString &text,
-            QObject *obj, const char *member,  QObject *parent): QAction(text, parent)
-  {
-    connect(this, SIGNAL(triggered()), obj, member);
-  }
-};
-//------------------------------------------------------------------------
-QString GMapDialog::formatLength(double l)
-{
-  double metricLength = l;
-  QString metricUnit = tr("meters");
-  int metricPrecision = 2;
-  if (l > 1000.0) {
-    metricLength = l/1000.0;
-    metricUnit = "km";
-    metricPrecision = 3;
-  }
-
-  double fpsLength = l*1000.0/25.4/12.0;
-  QString fpsUnit = tr("feet");
-  int fpsPrecision = 1;
-  if (fpsLength >5280.0) {
-    fpsLength /= 5280.0;
-    fpsUnit = tr("miles");
-    fpsPrecision = 3;
-  }
-  return QString(tr("Length: %1 %2\n  %3 %4")
-                .arg(metricLength, 0, 'f', metricPrecision)
-                .arg(metricUnit)
-                .arg(fpsLength, 0, 'f', fpsPrecision)
-                .arg(fpsUnit));
-
-}
-//------------------------------------------------------------------------
-void GMapDialog::appendWaypointInfo(QStandardItem *it, const GpxWaypoint &wpt)
-{
-  it->appendRow(new StandardItem(tr("Lat: %1").arg(wpt.getLocation().lat(), 0, 'f', 7)));
-  it->appendRow(new StandardItem(tr("Lng: %1").arg(wpt.getLocation().lng(), 0, 'f', 7)));
-  if (wpt.getDescription() != QString())
-    it->appendRow(new StandardItem(tr("Desc: %1").arg(wpt.getDescription())));
-  if (wpt.getComment() != QString() && wpt.getComment() != wpt.getDescription())
-    it->appendRow(new StandardItem(tr("Cmt: %1").arg(wpt.getComment())));
-  if (wpt.getElevation() > -50000)
-    it->appendRow(new StandardItem(tr("Ele: %1").arg(wpt.getElevation())));
-
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::appendTrackInfo(QStandardItem *it, const GpxTrack &trk)
-{
-  QDateTime startTime, stopTime;
-  bool first = true;
-  int count = 0;
-  foreach (const GpxTrackSegment &seg, trk.getTrackSegments()) {
-    foreach (const GpxTrackPoint &pt, seg.getTrackPoints()) {
-      count++;
-      QDateTime t = pt.getDateTime();
-      if (!t.isValid())
-       continue;
-      if (first) {
-       startTime = t;
-       stopTime = t;
-       first = false;
-      }
-      else {
-       if (t < startTime)
-         startTime = t;
-       if (t > stopTime)
-         stopTime = t;
-      }
-    }
-  }
-  if (startTime.isValid()) {
-    it->appendRow(new StandardItem(tr("Start: %1")
-                                   .arg(startTime.toString("yyyy-MMM-dd HH:mm:ss"))));
-    it->appendRow(new StandardItem(tr("Stop: %1")
-                                   .arg(stopTime.toString("yyyy-MMM-dd HH:mm:ss"))));
-  }
-  it->appendRow(new StandardItem(tr("Points: %1").arg(count)));
-
-  it->appendRow(new StandardItem(formatLength(trk.length())));
-
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::appendRouteInfo(QStandardItem *it, const GpxRoute &rte)
-{
-  it->appendRow(new StandardItem(formatLength(rte.length())));
-}
-
-//------------------------------------------------------------------------
-GMapDialog::GMapDialog(QWidget *parent, const QString &gpxFileName, QPlainTextEdit *te): QDialog(parent)
-{
-  ui.setupUi(this);
-  this->setWindowTitle(QString(appName) + " " + QString("Google Maps"));
-  gpx.read(gpxFileName);
-
-  mapWidget = new Map(this, gpx, te);
-  QHBoxLayout *lay = new QHBoxLayout(ui.frame);
-  lay->setContentsMargins(0, 0, 0, 0);
-  lay->addWidget(mapWidget);
-
-  model = new QStandardItemModel(this);
-
-  wptItem = new StandardItem(tr("Waypoints"));
-  wptItem->setCheckable(true);
-  wptItem->setCheckState(Qt::Checked);
-  model->appendRow(wptItem);
-  for (int i=0; i<gpx.getWaypoints().size(); i++) {
-    GpxWaypoint &wpt = gpx.getWaypoints()[i];
-    QStandardItem *it = new StandardItem(wpt.getName());
-    wptItem->appendRow(it);
-    it->setCheckable(true);
-    it->setCheckState(Qt::Checked);
-    it->setData(qVariantFromValue((void *)&wpt));
-    appendWaypointInfo(it, wpt);
-    wptList << it;
-  }
-
-  trkItem = new StandardItem(tr("Tracks"));
-  trkItem->setCheckable(true);
-  trkItem->setCheckState(Qt::Checked);
-  model->appendRow(trkItem);
-  for (int i=0; i<gpx.getTracks().size(); i++) {
-    GpxTrack &trk = gpx.getTracks()[i];
-    QStandardItem *it = new StandardItem(trk.getName());
-    trkItem->appendRow(it);
-    it->setCheckable(true);
-    it->setCheckState(Qt::Checked);
-    it->setData(qVariantFromValue((void *)&trk));
-    appendTrackInfo(it, trk);
-    trkList << it;
-  }
-
-  rteItem = new StandardItem(tr("Routes"));
-  rteItem->setCheckable(true);
-  rteItem->setCheckState(Qt::Checked);
-  model->appendRow(rteItem);
-  for (int i=0; i<gpx.getRoutes().size(); i++) {
-    GpxRoute &rte = gpx.getRoutes()[i];
-    QStandardItem *it = new StandardItem(rte.getName());
-    rteItem->appendRow(it);
-    it->setCheckable(true);
-    it->setCheckState(Qt::Checked);
-    it->setData(qVariantFromValue((void *)&rte));
-    appendRouteInfo(it, rte);
-    rteList << it;
-  }
-
-  ui.treeView->header()->hide();
-  ui.treeView->setModel(model);
-  ui.treeView->setExpandsOnDoubleClick(false);
-  connect(model, SIGNAL(itemChanged(QStandardItem *)),
-         this,  SLOT(itemChangedX(QStandardItem *)));
-  connect(mapWidget, SIGNAL(waypointClicked(int)), this, SLOT(waypointClickedX(int)));
-  connect(mapWidget, SIGNAL(routeClicked(int)), this, SLOT(routeClickedX(int)));
-  connect(mapWidget, SIGNAL(trackClicked(int)), this, SLOT(trackClickedX(int)));
-  connect(ui.treeView, SIGNAL(doubleClicked(const QModelIndex &)),
-         this, SLOT(treeDoubleClicked(const QModelIndex&)));
-  connect(ui.treeView->selectionModel(), SIGNAL(selectionChanged (const QItemSelection &,  const QItemSelection &)),
-         this, SLOT(selectionChangedX(const QItemSelection &,  const QItemSelection &)));
-                                               
-  ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
-  connect(ui.treeView, SIGNAL(customContextMenuRequested(const QPoint &)),
-         this, SLOT(showContextMenu(const QPoint &)));
-
-  connect(ui.copyButton, SIGNAL(clicked()), this, SLOT(copyButtonClickedX()));
-
-  ui.copyButton->hide(); // Hide for now, not working
-
-}
-
-//-------------------------------------------------------------------------
-void GMapDialog::itemChangedX(QStandardItem *it)
-{
-  bool show = (it->checkState() == Qt::Checked);
-  if (it == trkItem) {
-    if (show)
-      mapWidget->showTracks(gpx.getTracks());
-    else
-      mapWidget->hideAllTracks();
-  }
-
-  else if (it == wptItem) {
-    if (show)
-      mapWidget->showWaypoints(gpx.getWaypoints());
-    else
-      mapWidget->hideAllWaypoints();
-  }
-
-  else if (it == rteItem) {
-    if (show)
-      mapWidget->showRoutes(gpx.getRoutes());
-    else
-      mapWidget->hideAllRoutes();
-  }
-
-  else {
-    // Individual items, find the right one.
-    GpxItem *git = static_cast<GpxItem *>(it->data().value<void *>());
-    if (git != 0) {
-      git->setVisible(show);
-      for (int i=0; i<gpx.getWaypoints().size(); i++) {
-       if (&gpx.getWaypoints()[i] == git) {
-         mapWidget->setWaypointVisibility(i, show);
-       }
-      }
-      for (int i=0; i<gpx.getTracks().size(); i++) {
-       if (&gpx.getTracks()[i] == git) {
-         mapWidget->setTrackVisibility(i, show);
-       }
-      }
-      for (int i=0; i<gpx.getRoutes().size(); i++) {
-       if (&gpx.getRoutes()[i] == git) {
-         mapWidget->setRouteVisibility(i, show);
-       }
-      }
-    }
-  }
-}
-
-//-------------------------------------------------------------------------
-int GMapDialog::waypointIndex(QStandardItem *it)
-{
-  for (int j=0; j<wptList.size(); j++){
-    if (it == wptList[j])
-      return j;
-  }
-  return -1;
-}
-
-//-------------------------------------------------------------------------
-int GMapDialog::trackIndex(QStandardItem *it)
-{
-  for (int j=0; j<trkList.size(); j++){
-    if (it == trkList[j])
-      return j;
-  }
-  return -1;
-}
-
-//-------------------------------------------------------------------------
-int GMapDialog::routeIndex(QStandardItem *it)
-{
-  for (int j=0; j<rteList.size(); j++){
-    if (it == rteList[j])
-      return j;
-  }
-  return -1;
-}
-
-//-------------------------------------------------------------------------
-void GMapDialog::treeDoubleClicked(const QModelIndex &idx)
-{
-  QStandardItem *it = model->itemFromIndex(idx);
-  int i = waypointIndex(it);
-  if (i >= 0) {
-    it->setCheckState(Qt::Checked);
-    gpx.getWaypoints()[i].setVisible(true);
-    mapWidget->panTo(gpx.getWaypoints()[i].getLocation());
-    mapWidget->setWaypointVisibility(i, true);
-    return;
-  }
-  i = trackIndex(it);
-  if (i >= 0) {
-    mapWidget->frameTrack(i);
-    it->setCheckState(Qt::Checked);
-    gpx.getTracks()[i].setVisible(true);
-    mapWidget->setTrackVisibility(i, true);
-    return;
-  }
-  i = routeIndex(it);
-  if (i >= 0) {
-    mapWidget->frameRoute(i);
-    it->setCheckState(Qt::Checked);
-    gpx.getRoutes()[i].setVisible(true);
-    mapWidget->setRouteVisibility(i, true);
-    return;
-  }
-}
-
-//-------------------------------------------------------------------------
-void GMapDialog::waypointClickedX(int i)
-{
-  if (i>=0 && i < wptList.size()) {
-    QStandardItem *it = wptList[i];
-    QModelIndex idx = model->indexFromItem(it);
-    ui.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
-    ui.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
-  }
-}
-//-------------------------------------------------------------------------
-void GMapDialog::trackClickedX(int i)
-{
-  if (i>=0 && i <trkList.size()) {
-    QStandardItem *it = trkList[i];
-    QModelIndex idx = model->indexFromItem(it);
-    ui.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
-    ui.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
-  }
-}
-
-//-------------------------------------------------------------------------
-void GMapDialog::routeClickedX(int i)
-{
-  if (i>=0 && i <rteList.size()) {
-    QStandardItem *it = rteList[i];
-    QModelIndex idx = model->indexFromItem(it);
-    ui.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
-    ui.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
-  }
-}
-
-//-------------------------------------------------------------------------
-void GMapDialog::selectionChangedX (const QItemSelection &sel,  const QItemSelection &desel)
-{
-  int k=0;
-  foreach (QStandardItem*w, wptList) {
-    QModelIndex idx = model->indexFromItem(w);
-    if (desel.contains(idx))
-      mapWidget->setWaypointColorBlue(k);
-    if (sel.contains(idx))
-      mapWidget->setWaypointColorRed(k);
-    k++;
-  }
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::expandCollapseAll(const QList<QStandardItem *> &li,
-                                  QStandardItem *top, bool exp)
-{
-  ui.treeView->setExpanded(model->indexFromItem(top), exp);
-  foreach (QStandardItem*it, li) {
-    QModelIndex idx = model->indexFromItem(it);
-    ui.treeView->setExpanded(idx, exp);
-  }
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::expandAllWaypoints()
-{
-  expandCollapseAll(wptList, wptItem, true);
-}
-//------------------------------------------------------------------------
-void GMapDialog::expandAllTracks()
-{
-  expandCollapseAll(trkList, trkItem, true);
-}
-//------------------------------------------------------------------------
-void GMapDialog::expandAllRoutes()
-{
-  expandCollapseAll(rteList, rteItem, true);
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::collapseAllWaypoints()
-{
-  expandCollapseAll(wptList, wptItem,false);
-}
-//------------------------------------------------------------------------
-void GMapDialog::collapseAllTracks()
-{
-  expandCollapseAll(trkList, trkItem,false);
-}
-//------------------------------------------------------------------------
-void GMapDialog::collapseAllRoutes()
-{
-  expandCollapseAll(rteList, rteItem,false);
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::checkUncheckAll(const QList<QStandardItem *> &li,
-                                  QStandardItem *top, bool ck)
-{
-  top->setCheckState(ck ? Qt::Checked: Qt::Unchecked);
-  foreach (QStandardItem*it, li) {
-    it->setCheckState(ck ? Qt::Checked: Qt::Unchecked);
-  }
-}
-//------------------------------------------------------------------------
-void GMapDialog::showAllWaypoints()
-{
-  foreach (GpxWaypoint wpt, gpx.getWaypoints())
-    wpt.setVisible(true);
-  checkUncheckAll(wptList, wptItem, true);
-  mapWidget->showWaypoints(gpx.getWaypoints());
-}
-//------------------------------------------------------------------------
-void GMapDialog::showAllTracks()
-{
-  foreach (GpxTrack trk, gpx.getTracks())
-    trk.setVisible(true);
-  checkUncheckAll(trkList, trkItem, true);
-  mapWidget->showTracks(gpx.getTracks());
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::showAllRoutes()
-{
-  foreach (GpxRoute rte, gpx.getRoutes())
-    rte.setVisible(true);
-  checkUncheckAll(rteList, rteItem, true);
-  mapWidget->showRoutes(gpx.getRoutes());
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::hideAllWaypoints()
-{
-  foreach (GpxWaypoint wpt, gpx.getWaypoints())
-    wpt.setVisible(false);
-  checkUncheckAll(wptList, wptItem, false);
-  mapWidget->showWaypoints(gpx.getWaypoints());
-}
-//------------------------------------------------------------------------
-void GMapDialog::hideAllTracks()
-{
-  foreach (GpxTrack trk, gpx.getTracks())
-    trk.setVisible(false);
-  checkUncheckAll(trkList, trkItem, false);
-  mapWidget->showTracks(gpx.getTracks());
-
-}
-//------------------------------------------------------------------------
-void GMapDialog::hideAllRoutes()
-{
-  foreach (GpxRoute rte, gpx.getRoutes())
-    rte.setVisible(false);
-  checkUncheckAll(rteList, rteItem, false);
-  mapWidget->showRoutes(gpx.getRoutes());
-
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::showOnlyThisWaypoint()
-{
-  QList <GpxWaypoint> &tlist = gpx.getWaypoints();
-  for (int i=0; i<tlist.size(); i++) {
-    tlist[i].setVisible(i == menuIndex? true: false);
-    trkList[i]->setCheckState(i==menuIndex? Qt::Checked: Qt::Unchecked);
-  }
-  wptItem->setCheckState(Qt::Checked);
-  mapWidget->showWaypoints(gpx.getWaypoints());
-}
-//------------------------------------------------------------------------
-void GMapDialog::showOnlyThisTrack()
-{
-  QList <GpxTrack> &tlist = gpx.getTracks();
-  for (int i=0; i<tlist.size(); i++) {
-    tlist[i].setVisible(i == menuIndex? true: false);
-    trkList[i]->setCheckState(i==menuIndex? Qt::Checked: Qt::Unchecked);
-  }
-  trkItem->setCheckState(Qt::Checked);
-  mapWidget->showTracks(gpx.getTracks());
-
-}
-//------------------------------------------------------------------------
-void GMapDialog::showOnlyThisRoute()
-{
-  QList <GpxRoute> &rlist = gpx.getRoutes();
-  for (int i=0; i<rlist.size(); i++) {
-    rlist[i].setVisible(i == menuIndex? true: false);
-    rteList[i]->setCheckState(i==menuIndex? Qt::Checked: Qt::Unchecked);
-  }
-  rteItem->setCheckState(Qt::Checked);
-  mapWidget->showRoutes(gpx.getRoutes());
-
-}
-
-//------------------------------------------------------------------------
-void GMapDialog::showContextMenu(const QPoint &pt)
-{
-  QModelIndex idx = ui.treeView->indexAt(pt);
-  QStandardItem *it = model->itemFromIndex(idx);
-  int j;
-  if (model->indexFromItem(wptItem) == idx) {
-    QMenu menu(this);
-    menu.addAction(new TreeAction(tr("Show All Waypoints"), this, SLOT(showAllWaypoints()), &menu));
-    menu.addAction(new TreeAction(tr("Hide All Waypoints"), this, SLOT(hideAllWaypoints()),&menu));
-    menu.addAction(new TreeAction(tr("Expand All"), this, SLOT(expandAllWaypoints()),&menu));
-    menu.addAction(new TreeAction(tr("Collapse All"), this, SLOT(collapseAllWaypoints()),&menu));
-    menu.exec(ui.treeView->mapToGlobal(pt));
-  }
-  else if (model->indexFromItem(rteItem) == idx) {
-    QMenu menu(this);
-    menu.addAction(new TreeAction(tr("Show All Routes"), this, SLOT(showAllRoutes()), &menu));
-    menu.addAction(new TreeAction(tr("Hide All Routes"), this, SLOT(hideAllRoutes()),&menu));
-    menu.addAction(new TreeAction(tr("Expand All"), this, SLOT(expandAllRoutes()),&menu));
-    menu.addAction(new TreeAction(tr("Collapse All"), this, SLOT(collapseAllRoutes()),&menu));
-    menu.exec(ui.treeView->mapToGlobal(pt));
-  }
-  else if (model->indexFromItem(trkItem) == idx) {
-    QMenu menu(this);
-    menu.addAction(new TreeAction(tr("Show All Tracks"), this, SLOT(showAllTracks()), &menu));
-    menu.addAction(new TreeAction(tr("Hide All Tracks"), this, SLOT(hideAllTracks()),&menu));
-    menu.addAction(new TreeAction(tr("Expand All"), this, SLOT(expandAllTracks()),&menu));
-    menu.addAction(new TreeAction(tr("Collapse All"), this, SLOT(collapseAllTracks()),&menu));
-    menu.exec(ui.treeView->mapToGlobal(pt));
-  }
-  else if ((j = waypointIndex(it)) >=0) {
-    QMenu menu(this);
-    menu.addAction(new TreeAction(tr("Show Only This Waypoint"), this, SLOT(showOnlyThisWaypoint()), &menu));
-    menuIndex = j;
-    menu.exec(ui.treeView->mapToGlobal(pt));
-  }
-  else if ((j = trackIndex(it)) >=0) {
-    QMenu menu(this);
-    menu.addAction(new TreeAction(tr("Show Only This Track"), this, SLOT(showOnlyThisTrack()), &menu));
-    menuIndex = j;
-    menu.exec(ui.treeView->mapToGlobal(pt));
-  }
-  else if ((j = routeIndex(it)) >=0) {
-    QMenu menu(this);
-    menu.addAction(new TreeAction(tr("Show Only This Route"), this, SLOT(showOnlyThisRoute()), &menu));
-    menuIndex = j;
-    menu.exec(ui.treeView->mapToGlobal(pt));
-  }
-  else {
-  }
-}
-//------------------------------------------------------------------------
-void GMapDialog::copyButtonClickedX() {
-  
-}
diff --git a/gpsbabel/gui/gpx.cc b/gpsbabel/gui/gpx.cc
new file mode 100644 (file)
index 0000000..86e6da4
--- /dev/null
@@ -0,0 +1,245 @@
+// -*- C++ -*-
+// $Id: gpx.cpp,v 1.2 2009-08-28 17:08:55 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+
+
+#include <QFile>
+#include <QXmlInputSource>
+#include <QXmlSimpleReader>
+#include <QXmlDefaultHandler>
+#include "gpx.h"
+
+
+static QDateTime decodeDateTime(const QString s)
+{
+  QDateTime utc = QDateTime::fromString(s, "yyyy-MM-dd'T'HH:mm:ss'Z'");
+  return utc;
+}
+
+static bool trackIsEmpty(const GpxTrack &trk){
+  int count = 0;
+  for (int i=0; i< trk.getTrackSegments().size(); i++) {
+    for (int j=0; j<trk.getTrackSegments()[i].getTrackPoints().size(); j++) {
+      count++;
+    }
+  }
+  return count <=2 ;
+}
+
+class GpxHandler: public QXmlDefaultHandler
+{
+public:
+  GpxHandler(): QXmlDefaultHandler()
+
+  {
+    state = e_noop;
+  }
+
+  typedef enum {e_noop, e_wpt, e_trk,
+               e_trkpt, e_trkseg, e_rte, e_rtept} elementState;
+  QString textChars;
+  GpxWaypoint currentWpt;
+  QList <GpxWaypoint> wptList;
+
+  QList <GpxTrack> trkList;
+  GpxTrack currentTrk;
+  GpxTrackPoint currentTrkPt;
+  GpxTrackSegment currentTrkSeg;
+
+  QList <GpxRoute> rteList;
+  GpxRoute currentRte;
+  GpxRoutePoint currentRtePt;
+
+  elementState state;
+  QList <elementState> stateStack;
+
+  virtual bool startElement (const QString & ,
+                            const QString & localName, const QString & qName,
+                            const QXmlAttributes & atts )
+  {
+    if (localName == "wpt") {
+      currentWpt = GpxWaypoint();
+      double lat = atts.value("lat").toDouble();;
+      double lon = atts.value("lon").toDouble();;
+      currentWpt.setLocation(LatLng(lat, lon));
+      stateStack << state;
+      state = e_wpt;
+    }
+
+    else if (localName == "trk") {
+      stateStack << state;
+      state = e_trk;
+      currentTrk.clear();
+    }
+
+    else if (localName == "trkseg") {
+      stateStack << state;
+      state = e_trkseg;
+      currentTrkSeg.clear();
+    }
+
+    else if (localName == "trkpt") {
+      currentTrkPt = GpxTrackPoint();
+      double lat = atts.value("lat").toDouble();;
+      double lon = atts.value("lon").toDouble();;
+      currentTrkPt.setLocation(LatLng(lat, lon));
+      stateStack << state;
+      state = e_trkpt;
+    }
+
+    else if (localName == "rte") {
+      stateStack << state;
+      state = e_rte;
+      currentRte.clear();
+    }
+
+    else if (localName == "rtept") {
+      currentRtePt = GpxRoutePoint();
+      double lat = atts.value("lat").toDouble();;
+      double lon = atts.value("lon").toDouble();;
+      currentRtePt.setLocation(LatLng(lat, lon));
+      stateStack << state;
+      state = e_rtept;
+    }
+
+
+    else if (state == e_wpt ||
+            state == e_trkpt || state == e_trkseg || state == e_trk ||
+            state == e_rte || state == e_rtept) {
+    }
+    else {
+      //fprintf(stderr, "localName:  %s     name:  %s\n",
+      //localName.toStdString().c_str(), qName.toStdString().c_str());
+    }
+    return true;
+  };
+
+  virtual bool endElement (const QString & ,
+                          const QString & localName,
+                          const QString & qName)
+  {
+    if (localName == "wpt") {
+      state = stateStack.takeLast();
+      wptList << currentWpt;
+    }
+    else if (localName == "ele" && state == e_wpt) {
+      currentWpt.setElevation(textChars.toDouble());
+    }
+    else if (localName == "name" && state == e_wpt) {
+      currentWpt.setName(textChars);
+    }
+    else if (localName == "cmt" && state == e_wpt) {
+      currentWpt.setComment(textChars);
+    }
+    else if (localName == "desc" && state == e_wpt) {
+      currentWpt.setDescription(textChars);
+    }
+    else if (localName == "sym" && state == e_wpt) {
+      currentWpt.setSymbol(textChars);
+    }
+
+    else if (localName == "trkpt") {
+      state = stateStack.takeLast();
+      currentTrkSeg.addPoint(currentTrkPt);
+    }
+    else if (localName == "ele" && state == e_trkpt) {
+      currentTrkPt.setElevation(textChars.toDouble());
+    }
+    else if (localName == "time" && state == e_trkpt) {
+      currentTrkPt.setDateTime(decodeDateTime(textChars));
+    }
+
+    else if (localName == "trkseg") {
+      state = stateStack.takeLast();
+      currentTrk.addSegment(currentTrkSeg);
+    }
+
+    else if (localName == "trk") {
+      state = stateStack.takeLast();
+      if (!trackIsEmpty(currentTrk))
+       trkList << currentTrk;
+    }
+
+    else if (localName == "name" && state == e_trk) {
+      currentTrk.setName(textChars);
+    }
+    else if (localName == "number" && state == e_trk) {
+      currentTrk.setNumber(textChars.toInt());
+    }
+
+    else if (localName == "rte") {
+      state = stateStack.takeLast();
+      if (currentRte.getRoutePoints().size()>=2)
+       rteList << currentRte;
+    }
+
+    else if (localName == "rtept") {
+      state = stateStack.takeLast();
+      currentRte.addPoint(currentRtePt);
+    }
+
+    else if (localName == "name" && state == e_rtept) {
+      currentRtePt.setName(textChars);
+    }
+
+    else if (localName == "name" && state == e_rte) {
+      currentRte.setName(textChars);
+    }
+
+    else {
+      //fprintf(stderr, "end ---- localName:  %s     name:  %s\n\n",
+      //localName.toStdString().c_str(), qName.toStdString().c_str());
+    }
+    return true;
+  };
+
+  virtual bool characters(const QString &x)
+  {
+    textChars = x;
+    return true;
+  };
+};
+
+
+//------------------------------------------------------------------------
+
+bool Gpx::read(const QString & fileName)
+{
+  QFile file(fileName);
+  if (!file.open(QIODevice::ReadOnly))
+    return false;
+
+  QXmlInputSource xmlIn(&file);
+
+  QXmlSimpleReader reader;
+  GpxHandler gpxHandler;
+  reader.setContentHandler(&gpxHandler);
+
+  if (reader.parse(xmlIn)) {
+    wayPoints = gpxHandler.wptList;
+    tracks = gpxHandler.trkList;
+    routes = gpxHandler.rteList;
+    return true;
+  }
+  else
+    return false;
+}
diff --git a/gpsbabel/gui/gpx.cpp b/gpsbabel/gui/gpx.cpp
deleted file mode 100644 (file)
index 86e6da4..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-// -*- C++ -*-
-// $Id: gpx.cpp,v 1.2 2009-08-28 17:08:55 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-
-
-#include <QFile>
-#include <QXmlInputSource>
-#include <QXmlSimpleReader>
-#include <QXmlDefaultHandler>
-#include "gpx.h"
-
-
-static QDateTime decodeDateTime(const QString s)
-{
-  QDateTime utc = QDateTime::fromString(s, "yyyy-MM-dd'T'HH:mm:ss'Z'");
-  return utc;
-}
-
-static bool trackIsEmpty(const GpxTrack &trk){
-  int count = 0;
-  for (int i=0; i< trk.getTrackSegments().size(); i++) {
-    for (int j=0; j<trk.getTrackSegments()[i].getTrackPoints().size(); j++) {
-      count++;
-    }
-  }
-  return count <=2 ;
-}
-
-class GpxHandler: public QXmlDefaultHandler
-{
-public:
-  GpxHandler(): QXmlDefaultHandler()
-
-  {
-    state = e_noop;
-  }
-
-  typedef enum {e_noop, e_wpt, e_trk,
-               e_trkpt, e_trkseg, e_rte, e_rtept} elementState;
-  QString textChars;
-  GpxWaypoint currentWpt;
-  QList <GpxWaypoint> wptList;
-
-  QList <GpxTrack> trkList;
-  GpxTrack currentTrk;
-  GpxTrackPoint currentTrkPt;
-  GpxTrackSegment currentTrkSeg;
-
-  QList <GpxRoute> rteList;
-  GpxRoute currentRte;
-  GpxRoutePoint currentRtePt;
-
-  elementState state;
-  QList <elementState> stateStack;
-
-  virtual bool startElement (const QString & ,
-                            const QString & localName, const QString & qName,
-                            const QXmlAttributes & atts )
-  {
-    if (localName == "wpt") {
-      currentWpt = GpxWaypoint();
-      double lat = atts.value("lat").toDouble();;
-      double lon = atts.value("lon").toDouble();;
-      currentWpt.setLocation(LatLng(lat, lon));
-      stateStack << state;
-      state = e_wpt;
-    }
-
-    else if (localName == "trk") {
-      stateStack << state;
-      state = e_trk;
-      currentTrk.clear();
-    }
-
-    else if (localName == "trkseg") {
-      stateStack << state;
-      state = e_trkseg;
-      currentTrkSeg.clear();
-    }
-
-    else if (localName == "trkpt") {
-      currentTrkPt = GpxTrackPoint();
-      double lat = atts.value("lat").toDouble();;
-      double lon = atts.value("lon").toDouble();;
-      currentTrkPt.setLocation(LatLng(lat, lon));
-      stateStack << state;
-      state = e_trkpt;
-    }
-
-    else if (localName == "rte") {
-      stateStack << state;
-      state = e_rte;
-      currentRte.clear();
-    }
-
-    else if (localName == "rtept") {
-      currentRtePt = GpxRoutePoint();
-      double lat = atts.value("lat").toDouble();;
-      double lon = atts.value("lon").toDouble();;
-      currentRtePt.setLocation(LatLng(lat, lon));
-      stateStack << state;
-      state = e_rtept;
-    }
-
-
-    else if (state == e_wpt ||
-            state == e_trkpt || state == e_trkseg || state == e_trk ||
-            state == e_rte || state == e_rtept) {
-    }
-    else {
-      //fprintf(stderr, "localName:  %s     name:  %s\n",
-      //localName.toStdString().c_str(), qName.toStdString().c_str());
-    }
-    return true;
-  };
-
-  virtual bool endElement (const QString & ,
-                          const QString & localName,
-                          const QString & qName)
-  {
-    if (localName == "wpt") {
-      state = stateStack.takeLast();
-      wptList << currentWpt;
-    }
-    else if (localName == "ele" && state == e_wpt) {
-      currentWpt.setElevation(textChars.toDouble());
-    }
-    else if (localName == "name" && state == e_wpt) {
-      currentWpt.setName(textChars);
-    }
-    else if (localName == "cmt" && state == e_wpt) {
-      currentWpt.setComment(textChars);
-    }
-    else if (localName == "desc" && state == e_wpt) {
-      currentWpt.setDescription(textChars);
-    }
-    else if (localName == "sym" && state == e_wpt) {
-      currentWpt.setSymbol(textChars);
-    }
-
-    else if (localName == "trkpt") {
-      state = stateStack.takeLast();
-      currentTrkSeg.addPoint(currentTrkPt);
-    }
-    else if (localName == "ele" && state == e_trkpt) {
-      currentTrkPt.setElevation(textChars.toDouble());
-    }
-    else if (localName == "time" && state == e_trkpt) {
-      currentTrkPt.setDateTime(decodeDateTime(textChars));
-    }
-
-    else if (localName == "trkseg") {
-      state = stateStack.takeLast();
-      currentTrk.addSegment(currentTrkSeg);
-    }
-
-    else if (localName == "trk") {
-      state = stateStack.takeLast();
-      if (!trackIsEmpty(currentTrk))
-       trkList << currentTrk;
-    }
-
-    else if (localName == "name" && state == e_trk) {
-      currentTrk.setName(textChars);
-    }
-    else if (localName == "number" && state == e_trk) {
-      currentTrk.setNumber(textChars.toInt());
-    }
-
-    else if (localName == "rte") {
-      state = stateStack.takeLast();
-      if (currentRte.getRoutePoints().size()>=2)
-       rteList << currentRte;
-    }
-
-    else if (localName == "rtept") {
-      state = stateStack.takeLast();
-      currentRte.addPoint(currentRtePt);
-    }
-
-    else if (localName == "name" && state == e_rtept) {
-      currentRtePt.setName(textChars);
-    }
-
-    else if (localName == "name" && state == e_rte) {
-      currentRte.setName(textChars);
-    }
-
-    else {
-      //fprintf(stderr, "end ---- localName:  %s     name:  %s\n\n",
-      //localName.toStdString().c_str(), qName.toStdString().c_str());
-    }
-    return true;
-  };
-
-  virtual bool characters(const QString &x)
-  {
-    textChars = x;
-    return true;
-  };
-};
-
-
-//------------------------------------------------------------------------
-
-bool Gpx::read(const QString & fileName)
-{
-  QFile file(fileName);
-  if (!file.open(QIODevice::ReadOnly))
-    return false;
-
-  QXmlInputSource xmlIn(&file);
-
-  QXmlSimpleReader reader;
-  GpxHandler gpxHandler;
-  reader.setContentHandler(&gpxHandler);
-
-  if (reader.parse(xmlIn)) {
-    wayPoints = gpxHandler.wptList;
-    tracks = gpxHandler.trkList;
-    routes = gpxHandler.rteList;
-    return true;
-  }
-  else
-    return false;
-}
diff --git a/gpsbabel/gui/help.cc b/gpsbabel/gui/help.cc
new file mode 100644 (file)
index 0000000..98fa407
--- /dev/null
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+// $Id: help.cpp,v 1.8 2009-11-02 20:38:02 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#include <QUrl>
+#include <QDesktopServices>
+
+#include "help.h"
+#include "format.h"
+
+//------------------------------------------------------------------------
+void ShowHelp(const QString &urlIn)
+
+{
+  QString url = urlIn;
+  if (!url.contains(QRegExp("^http://"))) {
+    url = Format::getHtmlBase() + url;
+  }
+  QDesktopServices::openUrl(QUrl(url));
+}
+
+
+
diff --git a/gpsbabel/gui/help.cpp b/gpsbabel/gui/help.cpp
deleted file mode 100644 (file)
index 98fa407..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-// -*- C++ -*-
-// $Id: help.cpp,v 1.8 2009-11-02 20:38:02 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#include <QUrl>
-#include <QDesktopServices>
-
-#include "help.h"
-#include "format.h"
-
-//------------------------------------------------------------------------
-void ShowHelp(const QString &urlIn)
-
-{
-  QString url = urlIn;
-  if (!url.contains(QRegExp("^http://"))) {
-    url = Format::getHtmlBase() + url;
-  }
-  QDesktopServices::openUrl(QUrl(url));
-}
-
-
-
diff --git a/gpsbabel/gui/latlng.cc b/gpsbabel/gui/latlng.cc
new file mode 100644 (file)
index 0000000..11e506c
--- /dev/null
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+// $Id: latlng.cpp,v 1.2 2009-08-28 17:08:55 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#include <math.h>
+#include "latlng.h"
+
+
+// copied from the web somewhere.
+static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
+static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
+
+/** @brief Computes the arc, in radian, between two WGS-84 positions.
+  *
+  * The result is equal to <code>Distance(from,to)/EARTH_RADIUS_IN_METERS</code>
+  *    <code>= 2*asin(sqrt(h(d/EARTH_RADIUS_IN_METERS )))</code>
+  *
+  * where:<ul>
+  *    <li>d is the distance in meters between 'from' and 'to' positions.</li>
+  *    <li>h is the haversine function: <code>h(x)=sin²(x/2)</code></li>
+  * </ul>
+  *
+  * The haversine formula gives:
+  *    <code>h(d/R) = h(from.lat-to.lat)+h(from.lon-to.lon)+cos(from.lat)*cos(to.lat)</code>
+  *
+  * @sa http://en.wikipedia.org/wiki/Law_of_haversines
+  */
+static double ArcInRadians(const LatLng& from, const LatLng& to)
+{
+  double latitudeArc  = (from.lat() - to.lat()) * DEG_TO_RAD;
+  double longitudeArc = (from.lng() - to.lng()) * DEG_TO_RAD;
+  double latitudeH = sin(latitudeArc * 0.5);
+  latitudeH *= latitudeH;
+  double lontitudeH = sin(longitudeArc * 0.5);
+  lontitudeH *= lontitudeH;
+  double tmp = cos(from.lat()*DEG_TO_RAD) * cos(to.lat()*DEG_TO_RAD);
+  return 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH));
+}
+
+/** @brief Computes the distance, in meters, between two WGS-84 positions.
+ *
+ * The result is equal to <code>EARTH_RADIUS_IN_METERS*ArcInRadians(from,to)</code>
+ *
+ * @sa ArcInRadians
+ */
+static double DistanceInMeters(const LatLng& from, const LatLng& to) {
+  return EARTH_RADIUS_IN_METERS*ArcInRadians(from, to);
+}
+//------------------------------------------------------------------------
+
+double LatLng::haversineDistance(const LatLng &other) const
+{
+  return DistanceInMeters(*this, other);
+}
diff --git a/gpsbabel/gui/latlng.cpp b/gpsbabel/gui/latlng.cpp
deleted file mode 100644 (file)
index 11e506c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// -*- C++ -*-
-// $Id: latlng.cpp,v 1.2 2009-08-28 17:08:55 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#include <math.h>
-#include "latlng.h"
-
-
-// copied from the web somewhere.
-static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
-static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
-
-/** @brief Computes the arc, in radian, between two WGS-84 positions.
-  *
-  * The result is equal to <code>Distance(from,to)/EARTH_RADIUS_IN_METERS</code>
-  *    <code>= 2*asin(sqrt(h(d/EARTH_RADIUS_IN_METERS )))</code>
-  *
-  * where:<ul>
-  *    <li>d is the distance in meters between 'from' and 'to' positions.</li>
-  *    <li>h is the haversine function: <code>h(x)=sin²(x/2)</code></li>
-  * </ul>
-  *
-  * The haversine formula gives:
-  *    <code>h(d/R) = h(from.lat-to.lat)+h(from.lon-to.lon)+cos(from.lat)*cos(to.lat)</code>
-  *
-  * @sa http://en.wikipedia.org/wiki/Law_of_haversines
-  */
-static double ArcInRadians(const LatLng& from, const LatLng& to)
-{
-  double latitudeArc  = (from.lat() - to.lat()) * DEG_TO_RAD;
-  double longitudeArc = (from.lng() - to.lng()) * DEG_TO_RAD;
-  double latitudeH = sin(latitudeArc * 0.5);
-  latitudeH *= latitudeH;
-  double lontitudeH = sin(longitudeArc * 0.5);
-  lontitudeH *= lontitudeH;
-  double tmp = cos(from.lat()*DEG_TO_RAD) * cos(to.lat()*DEG_TO_RAD);
-  return 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH));
-}
-
-/** @brief Computes the distance, in meters, between two WGS-84 positions.
- *
- * The result is equal to <code>EARTH_RADIUS_IN_METERS*ArcInRadians(from,to)</code>
- *
- * @sa ArcInRadians
- */
-static double DistanceInMeters(const LatLng& from, const LatLng& to) {
-  return EARTH_RADIUS_IN_METERS*ArcInRadians(from, to);
-}
-//------------------------------------------------------------------------
-
-double LatLng::haversineDistance(const LatLng &other) const
-{
-  return DistanceInMeters(*this, other);
-}
diff --git a/gpsbabel/gui/main.cc b/gpsbabel/gui/main.cc
new file mode 100644 (file)
index 0000000..0e50b6e
--- /dev/null
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+// $Id: main.cpp,v 1.8 2010-06-06 00:49:08 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#define _CRT_SECURE_NO_DEPRECATE 1
+#include <QMessageBox>
+#include <QFile>
+#include <QCoreApplication>
+#include <QLibraryInfo>
+#include <QIcon>
+
+#include "mainwindow.h"
+#include "gmapdlg.h"
+
+#ifdef _WIN32
+const char *pathSeparator = ";";
+#else
+const char *pathSeparator = ":";
+#endif
+
+#if defined (Q_OS_MAC)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+//------------------------------------------------------------------------
+int main(int argc, char**argv)
+{
+  QApplication *app;
+  app = new QApplication(argc, argv);
+  app->setWindowIcon(QIcon(":/images/appicon.png"));
+
+  QString newPath = "PATH=" + QApplication::applicationDirPath() +
+    QString(pathSeparator) + getenv("PATH");
+  char *newPathEnv = new char[newPath.length() + 1];
+  strcpy(newPathEnv, newPath.toStdString().c_str());
+  putenv(newPathEnv);
+
+  QCoreApplication::setOrganizationName("GPSBabel");
+  QCoreApplication::setOrganizationDomain("gpsbabel.org");
+  QCoreApplication::setApplicationName("GPSBabel");
+
+  MainWindow mainWindow(0);
+  mainWindow.show();
+  app->exec();
+
+  return 0;
+}
diff --git a/gpsbabel/gui/main.cpp b/gpsbabel/gui/main.cpp
deleted file mode 100644 (file)
index 0e50b6e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// -*- C++ -*-
-// $Id: main.cpp,v 1.8 2010-06-06 00:49:08 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#define _CRT_SECURE_NO_DEPRECATE 1
-#include <QMessageBox>
-#include <QFile>
-#include <QCoreApplication>
-#include <QLibraryInfo>
-#include <QIcon>
-
-#include "mainwindow.h"
-#include "gmapdlg.h"
-
-#ifdef _WIN32
-const char *pathSeparator = ";";
-#else
-const char *pathSeparator = ":";
-#endif
-
-#if defined (Q_OS_MAC)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-//------------------------------------------------------------------------
-int main(int argc, char**argv)
-{
-  QApplication *app;
-  app = new QApplication(argc, argv);
-  app->setWindowIcon(QIcon(":/images/appicon.png"));
-
-  QString newPath = "PATH=" + QApplication::applicationDirPath() +
-    QString(pathSeparator) + getenv("PATH");
-  char *newPathEnv = new char[newPath.length() + 1];
-  strcpy(newPathEnv, newPath.toStdString().c_str());
-  putenv(newPathEnv);
-
-  QCoreApplication::setOrganizationName("GPSBabel");
-  QCoreApplication::setOrganizationDomain("gpsbabel.org");
-  QCoreApplication::setApplicationName("GPSBabel");
-
-  MainWindow mainWindow(0);
-  mainWindow.show();
-  app->exec();
-
-  return 0;
-}
diff --git a/gpsbabel/gui/mainwindow.cc b/gpsbabel/gui/mainwindow.cc
new file mode 100644 (file)
index 0000000..cbf30fb
--- /dev/null
@@ -0,0 +1,1350 @@
+// -*- C++ -*-
+// $Id: mainwindow.cpp,v 1.27 2010-11-01 03:30:42 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+#include <QDesktopServices>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QMimeData>
+#include <QProcess>
+#include <QSettings>
+#include <QTemporaryFile>
+#include <QTextStream>
+
+#include "mainwindow.h"
+#include "../gbversion.h"
+#include "aboutdlg.h"
+#include "advdlg.h"
+#include "appname.h"
+#include "babeldata.h"
+#include "donate.h"
+#include "filterdlg.h"
+#include "formatload.h"
+#include "gmapdlg.h"
+#include "help.h"
+#include "optionsdlg.h"
+#include "preferences.h"
+#include "processwait.h"
+#include "version_mismatch.h"
+#include "upgrade.h"
+
+const int BabelData::noType = -1;
+const int BabelData::fileType = 0;
+const int BabelData::deviceType = 1;
+
+#define FAKE_LANGUAGE_MENU 0
+
+//------------------------------------------------------------------------
+QString MainWindow::findBabelVersion()
+{
+  QProcess babel;
+  babel.start("gpsbabel", QStringList() << "-V");
+  if (!babel.waitForStarted())
+    return QString();
+  babel.closeWriteChannel();
+  if (!babel.waitForFinished())
+    return QString();
+
+  QString str = babel.readAll();
+  is_beta = str.contains("-beta");
+  str.replace("Version",  "");
+  str.replace("GPSBabel",  "");
+  str.replace(QRegExp("^[\\s]*"),  "");
+  str.replace(QRegExp("[\\s]+$"),  "");
+  str = str.simplified();
+  return str;
+}
+
+//------------------------------------------------------------------------
+// Decides whether available beta upgrades are suggested to user for download.
+bool MainWindow::allowBetaUpgrades()
+{
+  // If this is a beta version (which means the user consciously downloaded
+  // it and decided to be on the beta track or the user has ticked the 
+  // 'suggest beta upgrade' box, allow betas to be suggested for installation.
+  return is_beta || bd.allowBetaUpgrades;
+}
+
+//------------------------------------------------------------------------
+static QStringList getCharSets()
+{
+  QProcess babel;
+  babel.start("gpsbabel", QStringList() << "-l");
+  if (!babel.waitForStarted())
+    return QStringList();
+  babel.closeWriteChannel();
+  if (!babel.waitForFinished())
+    return QStringList();
+
+  QStringList strList;
+  QTextStream tstream(babel.readAll());
+  while(!tstream.atEnd()) {
+    QString l = tstream.readLine();
+    if (QRegExp("^\\*").indexIn(l) == 0) {
+      l.replace(QRegExp("^[\\*\\s]*"),  "");
+      l.replace(QRegExp("[\\s]+$"),  "");
+      strList << l;
+    }
+  }
+  return strList;
+}
+
+//------------------------------------------------------------------------
+static QString MakeOptions(const QList<FormatOption>& options)
+{
+  QString str;
+  for (int i=0; i<options.size(); i++) {
+    if (options[i].getSelected()) {
+      str += ",";
+      str += options[i].getName();
+      if (options[i].getType() == FormatOption::OPTbool) {
+        str += "=1";
+      } else {
+        str += "=" + options[i].getValue().toString();
+      }
+    } else {
+      if (options[i].getType() == FormatOption::OPTbool) {
+        str += "," + options[i].getName() + "=0";
+      }
+    }
+  }
+  return str;
+}
+
+//------------------------------------------------------------------------
+static QString MakeOptionsNoLeadingComma(const QList<FormatOption>& options)
+{
+  QString str = MakeOptions(options);
+  return (str.length()) ? str.mid(1) : str;
+
+}
+
+//------------------------------------------------------------------------
+MainWindow::MainWindow(QWidget* parent): QMainWindow(parent)
+{
+  loadFormats();
+  ui.setupUi(this);
+  setWindowTitle(appName);
+  babelVersion = findBabelVersion();
+  fmtChgInterlock = false;
+  loadDeviceNameCombos();
+  loadCharSetCombos();
+
+  connect(ui.inputFileOptBtn,        SIGNAL(clicked()), this, SLOT(inputFileOptBtnClicked()));
+  connect(ui.inputDeviceOptBtn,      SIGNAL(clicked()), this, SLOT(inputDeviceOptBtnClicked()));
+  connect(ui.inputFileNameBrowseBtn, SIGNAL(clicked()), this, SLOT(browseInputFile()));
+
+  ui.outputFileOptBtn->setAutoExclusive(false);
+  ui.outputDeviceOptBtn->setAutoExclusive(false);
+  connect(ui.outputFileOptBtn,        SIGNAL(clicked()), this, SLOT(outputFileOptBtnClicked()));
+  connect(ui.outputDeviceOptBtn,      SIGNAL(clicked()), this, SLOT(outputDeviceOptBtnClicked()));
+  connect(ui.outputFileNameBrowseBtn, SIGNAL(clicked()), this, SLOT(browseOutputFile()));
+
+  connect(ui.actionQuit, SIGNAL(triggered()), this, SLOT(closeActionX()));
+  connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(helpActionX()));
+  connect(ui.actionAbout, SIGNAL(triggered()), this, SLOT(aboutActionX()));
+  connect(ui.actionVisit_Website, SIGNAL(triggered()), this, SLOT(visitWebsiteActionX()));
+  connect(ui.actionMake_a_Donation, SIGNAL(triggered()), this, SLOT(donateActionX()));
+  connect(ui.actionUpgradeCheck, SIGNAL(triggered()), this, SLOT(upgradeCheckActionX()));
+  connect(ui.actionPreferences, SIGNAL(triggered()), this, SLOT(preferencesActionX()));
+
+  connect(ui.inputFormatCombo,  SIGNAL(currentIndexChanged(int)),
+         this,                 SLOT(inputFormatChanged(int)));
+  connect(ui.outputFormatCombo, SIGNAL(currentIndexChanged(int)),
+         this,                 SLOT(outputFormatChanged(int)));
+  connect(ui.inputOptionsBtn,   SIGNAL(clicked()),
+         this,                 SLOT(inputOptionButtonClicked()));
+  connect(ui.outputOptionsBtn , SIGNAL(clicked()),
+         this,                 SLOT(outputOptionButtonClicked()));
+  connect(ui.moreOptionButton , SIGNAL(clicked()),
+         this,                 SLOT(moreOptionButtonClicked()));
+
+  connect(ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyActionX()));
+  connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(closeActionX()));
+  connect(ui.xlateFiltersBtn, SIGNAL(clicked()), this, SLOT(filtersClicked()));
+
+  connect(ui.inputFileNameText, SIGNAL(textEdited(QString)), this, SLOT(inputFileNameEdited()));
+  connect(ui.outputFileNameText, SIGNAL(textEdited(QString)), this, SLOT(outputFileNameEdited()));
+
+
+  ui.buttonBox->button(QDialogButtonBox::Apply)->setIcon(QIcon(":images/runit.png"));
+  ui.buttonBox->button(QDialogButtonBox::Close)->setIcon(QIcon(":images/exit.png"));
+
+
+  ui.inputOptionsText->setReadOnly(true);
+  ui.outputOptionsText->setReadOnly(true);
+#if 0
+  // 02/28/10  - let's try letting people edit these outside the browse.
+  ui.inputFileNameText->setReadOnly(true);
+  ui.outputFileNameText->setReadOnly(true);
+#else
+  setAcceptDrops(true);
+#endif
+  ui.wayPtLabel->setText("");
+  ui.trackLabel->setText("");
+  ui.routeLabel->setText("");
+  lights[0] = QPixmap::fromImage(QImage(":images/00.png").scaledToHeight(20, Qt::SmoothTransformation));
+  lights[1] = QPixmap::fromImage(QImage(":images/01.png").scaledToHeight(20, Qt::SmoothTransformation));
+  lights[2] = QPixmap::fromImage(QImage(":images/10.png").scaledToHeight(20, Qt::SmoothTransformation));
+  lights[3] = QPixmap::fromImage(QImage(":images/11.png").scaledToHeight(20, Qt::SmoothTransformation));
+
+  ui.outputWindow->setReadOnly(true);
+
+  langPath = QApplication::applicationDirPath();
+  langPath.append("/translations/");
+
+  // Start up in the current system language.
+  loadLanguage(QLocale::system().name());
+#if FAKE_LANGUAGE_MENU
+  createLanguageMenu();
+#endif
+
+  //--- Restore from registry
+  restoreSettings();
+
+  upgrade = new UpgradeCheck(parent, formatList, bd);
+  if (bd.startupVersionCheck) {
+    upgrade->checkForUpgrade(babelVersion, bd.upgradeCheckTime, 
+                             allowBetaUpgrades());
+  }
+
+  if (!bd.ignoreVersionMismatch && babelVersion != VERSION) {
+    VersionMismatch vm(0, babelVersion, QString(VERSION));
+
+    vm.exec();
+    bd.ignoreVersionMismatch = vm.neverAgain();
+  }
+}
+
+//------------------------------------------------------------------------
+MainWindow::~MainWindow()
+{
+  if (upgrade)
+    delete upgrade;
+}
+//------------------------------------------------------------------------
+// Dynamic language switching courtesy of 
+// http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application
+// We create the menu entries dynamically, dependant on the existing 
+// translations.
+#if FAKE_LANGUAGE_MENU
+void MainWindow::createLanguageMenu(void)
+{
+    QActionGroup* langGroup = new QActionGroup(ui.menuHelp);
+    langGroup->setExclusive(true);
+    connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotLanguageChanged(QAction *)));
+
+    // format systems language
+    QString defaultLocale = QLocale::system().name();       // e.g. "de_DE"
+    defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de"
+
+    QDir dir(langPath);
+    QStringList fileNames = dir.entryList(QStringList("GPSBabelFE*.qm"));
+
+    for (int i = 0; i < fileNames.size(); ++i) {
+        // get locale extracted by filename
+        QString locale;
+        locale = fileNames[i];                  // "TranslationExample_de.qm"
+        locale.truncate(locale.lastIndexOf('.'));   // "TranslationExample_de"
+        locale.remove(0, locale.indexOf('_') + 1);   // "de"
+
+        QString lang = QLocale::languageToString(QLocale(locale).language());
+
+        QAction *action = new QAction(lang, this);
+        action->setCheckable(true);
+        action->setData(locale);
+
+        ui.menuHelp->addAction(action);
+        langGroup->addAction(action);
+
+        // set default translators and language checked
+        if (defaultLocale == locale) {
+            action->setChecked(true);
+        }
+    }
+}
+#endif //  FAKE_LANGUAGE_MENU
+
+//------------------------------------------------------------------------
+// Called every time, when a menu entry of the language menu is called
+void MainWindow::slotLanguageChanged(QAction* action)
+{
+  if (0 != action) {
+    // load the language dependant on the action content.
+    loadLanguage(action->data().toString());
+  }
+}
+
+void MainWindow::switchTranslator(QTranslator& translator, const QString& filename)
+{
+  // remove the old translator
+  qApp->removeTranslator(&translator);
+
+  QString full_filename(langPath + "/" + filename);
+
+  // load the new translator
+  if (translator.load(full_filename))
+    qApp->installTranslator(&translator);
+}
+
+void MainWindow::loadLanguage(const QString& rLanguage)
+{
+  if (currLang != rLanguage) {
+    currLang = rLanguage;
+    QLocale locale = QLocale(currLang);
+    QLocale::setDefault(locale);
+    QString languageName = QLocale::languageToString(locale.language());
+
+    switchTranslator(translator, QString("gpsbabelfe_%1.qm").arg(rLanguage));
+    switchTranslator(translatorCore, QString("gpsbabel__%1.qm").arg(rLanguage));
+    switchTranslator(translatorQt, QString("qt_%1.qm").arg(rLanguage));
+  }
+}
+
+void MainWindow::changeEvent(QEvent* event)
+{
+    if (0 != event) {
+        switch(event->type()) {
+        // This event is sent if a translator is loaded.
+        case QEvent::LanguageChange:
+            ui.retranslateUi(this);
+            break;
+        // This event is sent if the system language changes.
+        case QEvent::LocaleChange:
+            {
+                QString locale = QLocale::system().name();
+                locale.truncate(locale.lastIndexOf('_'));
+                loadLanguage(locale);
+            }
+           break;
+        default:
+           break;
+        }
+    }
+    QMainWindow::changeEvent(event);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::loadInputDeviceNameCombo(const QString &format)
+{
+  ui.inputDeviceNameCombo->clear();
+  // Later, we can probe the system for multiple USB devices and populate 
+  // here.
+  if (formatSupportsUSB(format))
+    ui.inputDeviceNameCombo->addItem("usb:");
+  if (formatSupportsSerial(format))
+    osLoadDeviceNameCombos(ui.inputDeviceNameCombo);
+  // If only one choice, just disable it.
+  ui.inputDeviceNameCombo->setEnabled(ui.inputDeviceNameCombo->count() > 1);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::loadOutputDeviceNameCombo(const QString &format)
+{
+  ui.outputDeviceNameCombo->clear();
+  // Later, we can probe the system for multiple USB devices and populate 
+  // here.
+  if (formatSupportsUSB(format))
+    ui.outputDeviceNameCombo->addItem("usb:");
+  if (formatSupportsSerial(format))
+    osLoadDeviceNameCombos(ui.outputDeviceNameCombo);
+  // If only one choice, just disable it.
+  ui.outputDeviceNameCombo->setEnabled(ui.outputDeviceNameCombo->count() > 1);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::loadDeviceNameCombos()
+{
+  loadInputDeviceNameCombo("");
+  loadOutputDeviceNameCombo("");
+}
+//------------------------------------------------------------------------
+void MainWindow::loadCharSetCombos()
+{
+  charSets = getCharSets();
+
+  ui.inputCharSetCombo->clear();
+  ui.outputCharSetCombo->clear();
+  ui.inputCharSetCombo->addItem(tr("default"), QVariant(-1));
+  ui.outputCharSetCombo->addItem(tr("default"), QVariant(-1));
+  for (int i=0; i<charSets.size(); i++) {
+    ui.inputCharSetCombo->addItem(charSets[i], QVariant(i));
+    ui.outputCharSetCombo->addItem(charSets[i], QVariant(i));
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::checkCharSetCombos()
+{
+  ui.inputCharSetCombo->setEnabled(bd.enableCharSetXform);
+  ui.outputCharSetCombo->setEnabled(bd.enableCharSetXform);
+  ui.inputCharSetCombo->setVisible(bd.enableCharSetXform);
+  ui.outputCharSetCombo->setVisible(bd.enableCharSetXform);
+}
+//------------------------------------------------------------------------
+void MainWindow::inputFileOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  QString fmt = bd.inputFileFormat;
+  ui.inputStackedWidget->setCurrentWidget(ui.inputFilePage);
+  QList<int>indices = inputFileFormatIndices();
+  ui.inputFormatCombo->clear();
+  for (int i=0; i<indices.size(); i++) {
+    int k = indices[i];
+    if (!formatList[k].isHidden())
+      ui.inputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+  }
+  setComboToFormat(ui.inputFormatCombo, fmt, true);
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+void MainWindow::inputDeviceOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  QString fmt = bd.inputDeviceFormat;
+  ui.inputStackedWidget->setCurrentWidget(ui.inputDevicePage);
+  QList<int>indices = inputDeviceFormatIndices();
+  ui.inputFormatCombo->clear();
+  for (int i=0; i<indices.size(); i++) {
+    int k = indices[i];
+    if (!formatList[k].isHidden())
+      ui.inputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+  }
+  setComboToFormat(ui.inputFormatCombo, fmt, false);
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+void MainWindow:: outputFileOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  if (ui.outputFileOptBtn->isChecked()) {
+    ui.outputFilePage->setEnabled(true);
+    ui.outputDeviceOptBtn->setChecked(false);
+    QString fmt = bd.outputFileFormat;
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+    QList<int>indices = outputFileFormatIndices();
+    ui.outputFormatCombo->clear();
+    for (int i=0; i<indices.size(); i++) {
+      int k = indices[i];
+      ui.outputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+    }
+    setComboToFormat(ui.outputFormatCombo, fmt, true);
+  }
+  else {
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+    ui.outputFilePage->setEnabled(false);
+  }
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+void MainWindow:: outputDeviceOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  if (ui.outputDeviceOptBtn->isChecked()) {
+    ui.outputDevicePage->setEnabled(true);
+    ui.outputFileOptBtn->setChecked(false);
+    QString fmt = bd.outputDeviceFormat;
+    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
+    QList<int>indices = outputDeviceFormatIndices();
+    ui.outputFormatCombo->clear();
+    for (int i=0; i<indices.size(); i++) {
+      int k = indices[i];
+      ui.outputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+    }
+    setComboToFormat(ui.outputFormatCombo, fmt, false);
+  }
+  else {
+    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
+    ui.outputDevicePage->setEnabled(false);
+  }
+  fmtChgInterlock = false;
+}
+void MainWindow::inputFileNameEdited()
+{
+  bd.inputFileNames.clear();
+  bd.inputFileNames << ui.inputFileNameText->text();
+}
+
+void MainWindow::outputFileNameEdited()
+{
+  bd.outputFileName = ui.outputFileNameText->text();
+
+}
+
+//------------------------------------------------------------------------
+QString MainWindow::filterForFormat(int idx)
+{
+  QString str = formatList[idx].getDescription();
+  str.replace(QRegExp("\\("), "[");
+  str.replace(QRegExp("\\)"), "]");
+  QStringList extensions = formatList[idx].getExtensions();
+
+  // If we don't have any meaningful extensions available for this format,
+  // don't be clever here; just fall through to "All files" case.
+  if (extensions.size() > 0 && !extensions[0].isEmpty()) {
+    str += " (";
+    for (int i=0; i<extensions.size(); i++) {
+      if (i!= 0)
+        str += " ";
+      str += "*." + extensions[i];
+    }
+    str += ");;";
+  }
+  str += "All Files (*.*)";
+  return str;
+}
+//------------------------------------------------------------------------
+QString MainWindow::ensureExtensionPresent(const QString &name, int idx)
+{
+  QString outname = name;
+  if (QFileInfo(name).suffix().length() == 0) {
+    QStringList extensions = formatList[idx].getExtensions();
+    if (extensions.size() > 0)
+      outname += "." + extensions[0];
+  }
+  return outname;
+}
+
+//------------------------------------------------------------------------
+bool MainWindow::filterForFormatIncludes(int idx, const QString &fmt)
+{
+  QStringList extensions = formatList[idx].getExtensions();
+  for (int i=0; i<extensions.size(); i++) {
+    if (fmt == extensions[i])
+      return true;
+  }
+  return false;
+}
+
+//------------------------------------------------------------------------
+int MainWindow::currentComboFormatIndex(QComboBox *comboBox)
+{
+  int idx = comboBox->currentIndex();
+  if (idx<0 || idx >= comboBox->count()) {
+    //    QMessageBox::critical(0, appName, "*** Internal Error -- current combo index is invalid!");
+    return 0;
+  }
+  return comboBox->itemData(idx).toInt();
+}
+//------------------------------------------------------------------------
+void MainWindow::browseInputFile()
+{
+  QString startFile = bd.inputFileNames.size() ? bd.inputFileNames[0] : bd.inputBrowse;
+  int idx = currentComboFormatIndex(ui.inputFormatCombo);
+  QFileInfo finfo(startFile);
+  if (!finfo.isDir() && (!filterForFormatIncludes(idx, finfo.suffix()))) {
+    startFile = finfo.dir().absolutePath();
+  }
+
+  QStringList userList =
+    QFileDialog::getOpenFileNames(0, tr("Select one or more input files"),
+                                 startFile,
+                                 filterForFormat(idx));
+  if (userList.size()) {
+    bd.inputBrowse = userList[0];
+    bd.inputFileNames = userList;
+    QString str;
+    for (int i=0; i<bd.inputFileNames.size(); i++) {
+      if (i != 0)
+        str += ", ";
+      str += "\"" + bd.inputFileNames[i] + "\"";
+    }
+    ui.inputFileNameText->setText(str);
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::browseOutputFile()
+{
+  int idx = currentComboFormatIndex(ui.outputFormatCombo);
+  QString startFile = bd.outputFileName.length() == 0 ? bd.outputBrowse : bd.outputFileName;
+  QFileInfo finfo(startFile);
+  if (!finfo.isDir() && (!filterForFormatIncludes(idx, finfo.suffix()))) {
+    startFile = finfo.dir().absolutePath();
+  }
+
+  QString str =
+    QFileDialog::getSaveFileName(0, tr("Output File Name"),
+                                startFile,
+                                filterForFormat(idx));
+  if (str.length() != 0) {
+    str = ensureExtensionPresent(str, idx);
+    bd.outputBrowse = str;
+    bd.outputFileName = str;
+    ui.outputFileNameText->setText(str);
+  }
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::inputFileFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isReadSomething() && formatList[i].isFileFormat())
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::inputDeviceFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isReadSomething() && formatList[i].isDeviceFormat())
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::outputFileFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isWriteSomething() && formatList[i].isFileFormat())
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::outputDeviceFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isWriteSomething() && formatList[i].isDeviceFormat())
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+void MainWindow::loadFormats()
+{
+  if (!FormatLoad().getFormats(formatList)) {
+    QMessageBox::information(0, QString(appName),
+                            tr("Error reading format configuration.  "
+                               "Check that the backend program \"gpsbabel\" is properly installed "
+                               "and is in the current PATH\n\n"
+                               "This program cannot continue."));
+   exit(1);
+  }
+  if (inputFileFormatIndices().size() == 0 ||
+      inputDeviceFormatIndices().size() == 0 ||
+      outputFileFormatIndices().size() == 0 ||
+      outputDeviceFormatIndices().size() == 0) {
+    QMessageBox::information(0, QString(appName),
+                            tr("Some file/device formats were not found during initialization.  "
+                               "Check that the backend program \"gpsbabel\" is properly installed "
+                               "and is in the current PATH\n\n"
+                               "This program cannot continue."));
+    exit(1);
+  }
+}
+//------------------------------------------------------------------------
+static int iconIndex(bool a, bool b)
+{
+  return ((a?1:0)*2) + (b?1:0);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::setIndicatorLights(QLabel *label, const QString &type, int code)
+{
+  label->setPixmap(lights[code]);
+  QString s;
+  switch (code)
+    {
+    default:
+    case 0:
+      s = tr("Input and output formats do not support %1").arg(type);
+      break;
+    case 1:
+      s = tr("Input does not support %1; output format supports %2").arg(type).arg(type);
+      break;
+    case 2:
+      s = tr("Input format supports %1; output format does not support %2").arg(type).arg(type);
+      break;
+    case 3:
+      s = tr("Both input and output formats support %1").arg(type);
+      break;
+    }
+  label->setToolTip(s);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::crossCheckInOutFormats()
+{
+  if (ui.inputFormatCombo->count() == 0 ||
+      ui.outputFormatCombo->count() == 0) {
+    // During format/device switch this is true
+    return;
+  }
+  Format ifmt = formatList[currentComboFormatIndex(ui.inputFormatCombo)];
+  Format ofmt = formatList[currentComboFormatIndex(ui.outputFormatCombo)];
+
+  ui.xlateWayPtsCk->setEnabled(ifmt.isReadWaypoints() && ofmt.isWriteWaypoints());
+  ui.xlateTracksCk->setEnabled(ifmt.isReadTracks()    && ofmt.isWriteTracks());
+  ui.xlateRoutesCk->setEnabled(ifmt.isReadRoutes()    && ofmt.isWriteRoutes());
+
+  setIndicatorLights(ui.wayPtLabel, tr("waypoints"), iconIndex(ifmt.isReadWaypoints(), ofmt.isWriteWaypoints()));
+  setIndicatorLights(ui.trackLabel, tr("tracks"), iconIndex(ifmt.isReadTracks(), ofmt.isWriteTracks()));
+  setIndicatorLights(ui.routeLabel, tr("routes"), iconIndex(ifmt.isReadRoutes(), ofmt.isWriteRoutes()));
+}
+
+//------------------------------------------------------------------------
+void MainWindow::displayOptionsText(QLineEdit *le, QComboBox *combo, bool isInput)
+{
+  int fidx = combo->itemData(combo->currentIndex()).toInt();
+  if (isInput)
+    le->setText(MakeOptionsNoLeadingComma(formatList[fidx].getInputOptions()));
+  else
+    le->setText(MakeOptionsNoLeadingComma(formatList[fidx].getOutputOptions()));
+
+}
+
+//------------------------------------------------------------------------
+void MainWindow::setComboToFormat(QComboBox *comboBox, const QString &name, bool isFile)
+{
+  int fidx = -1;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].getName() == name &&
+       formatList[i].isFileFormat() == isFile) {
+      fidx = i;
+      break;
+    }
+  }
+  if (fidx >=0) {
+    for (int i=0; i<comboBox->count(); i++) {
+      if (comboBox->itemData(i).toInt() == fidx) {
+       comboBox->setCurrentIndex(i);
+       break;
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+bool MainWindow::formatSupportsUSB(const QString &format)
+{
+    return (format == "garmin" || format == "delbin");
+}
+
+//------------------------------------------------------------------------
+bool MainWindow::formatSupportsSerial(const QString &format)
+{
+    return (format != "delbin");
+}
+
+//------------------------------------------------------------------------
+void MainWindow::inputFormatChanged(int comboIdx)
+{
+  if (fmtChgInterlock)
+    return;
+  int fidx = ui.inputFormatCombo->itemData(comboIdx).toInt();
+  ui.inputOptionsBtn->setEnabled(formatList[fidx].getInputOptions().size()>0);
+  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+  crossCheckInOutFormats();
+
+  if (ui.inputFileOptBtn->isChecked())
+    bd.inputFileFormat =formatList[fidx].getName();
+  else
+    bd.inputDeviceFormat = formatList[fidx].getName();
+
+  loadInputDeviceNameCombo(formatList[fidx].getName());
+}
+
+//------------------------------------------------------------------------
+void MainWindow::outputFormatChanged(int comboIdx)
+{
+  if (fmtChgInterlock)
+    return;
+  int fidx = ui.outputFormatCombo->itemData(comboIdx).toInt();
+  ui.outputOptionsBtn->setEnabled(formatList[fidx].getOutputOptions().size()>0);
+  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+  crossCheckInOutFormats();
+
+  if (ui.outputFileOptBtn->isChecked())
+    bd.outputFileFormat =formatList[fidx].getName();
+  else if (ui.outputDeviceOptBtn->isChecked())
+    bd.outputDeviceFormat = formatList[fidx].getName();
+
+  loadOutputDeviceNameCombo(formatList[fidx].getName());
+}
+
+//------------------------------------------------------------------------
+void MainWindow::inputOptionButtonClicked()
+{
+  int fidx = currentComboFormatIndex(ui.inputFormatCombo);
+  if (formatList[fidx].getInputOptionsRef()->size() == 0) {
+    QMessageBox::information
+      (0, appName,
+       tr("There are no input options for format \"%1\"").arg(formatList[fidx].getDescription()));
+  }
+  else {
+    OptionsDlg optionDlg(0,
+                        formatList[fidx].getName(),
+                        formatList[fidx].getInputOptionsRef(),
+                        formatList[fidx].getHtml());
+    optionDlg.setWindowTitle(QString(appName) + " - " + tr("Options for %1").arg(formatList[fidx].getName()));
+    optionDlg.exec();
+    displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::outputOptionButtonClicked()
+{
+  int fidx = currentComboFormatIndex(ui.outputFormatCombo);
+  if (formatList[fidx].getOutputOptionsRef()->size() == 0) {
+    QMessageBox::information
+      (0, appName,
+       tr("There are no output options for format \"%1\"").arg(formatList[fidx].getDescription()));
+  }
+  else {
+    OptionsDlg optionDlg(0, 
+                        formatList[fidx].getName(), 
+                        formatList[fidx].getOutputOptionsRef(),
+                        formatList[fidx].getHtml());
+    optionDlg.setWindowTitle(QString(appName) + " - " + tr("Options for %1").arg(formatList[fidx].getName()));
+    optionDlg.exec();
+    displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+  }
+}
+
+
+
+//------------------------------------------------------------------------
+bool MainWindow::isOkToGo()
+{
+  if (!((ui.xlateWayPtsCk->isChecked() && ui.xlateWayPtsCk->isEnabled()) ||
+       (ui.xlateRoutesCk->isChecked() && ui.xlateRoutesCk->isEnabled()) ||
+       (ui.xlateTracksCk->isChecked() && ui.xlateTracksCk->isEnabled()))) {
+    QMessageBox::information(0, QString(appName), tr("No valid waypoints/routes/tracks translation specified"));
+    return false;
+  }
+
+  // Paper over what didn't happen in inputBrowse() if the user edited
+  // the filename fields directly.
+  if ((bd.inputType == BabelData::fileType) &&
+      (bd.inputFileNames.size() == 0) &&
+      (!ui.inputFileNameText->text().isEmpty())) {
+    bd.inputFileNames << ui.inputFileNameText->text();
+  }
+  if ((bd.outputType == BabelData::fileType) &&
+      (bd.outputFileName.size() == 0) &&
+      (!ui.outputFileNameText->text().isEmpty())) {
+    bd.outputFileName = ui.outputFileNameText->text();
+  }
+
+  if ((bd.inputType == BabelData::fileType) &&
+      (bd.inputFileNames.size() == 0)) {
+    QMessageBox::information(0, QString(appName), tr("No input file specified"));
+    return false;
+  }
+
+  if (bd.outputType == BabelData::noType && bd.previewGmap == true) {
+  }
+  if (bd.outputType == BabelData::noType && bd.previewGmap == false) {
+    QMessageBox::information(0, QString(appName), tr("No valid output specified"));
+    return false;
+  }
+  else if (bd.outputType == BabelData::fileType &&
+          bd.outputFileName.length() == 0) {
+    QMessageBox::information(0, QString(appName), tr("No output file specified"));
+    return false;
+  }
+  return true;
+}
+
+//------------------------------------------------------------------------
+bool MainWindow::runGpsbabel(const QStringList &args, QString &errorString,
+                         QString &outputString)
+{
+  QProcess *proc = new QProcess(0);
+  QString name = "gpsbabel";
+  proc->start(name, args);
+  ProcessWaitDialog *waitDlg = new ProcessWaitDialog(0, proc);
+
+  if (proc->state() == QProcess::NotRunning) {
+    errorString = QString(tr("Process \"%1\" did not start")).arg(name);
+    return false;
+  }
+
+  waitDlg->show();
+  waitDlg->exec();
+  int exitCode = -1;
+  bool retStatus = false;
+  if (waitDlg->getExitedNormally()) {
+    exitCode = waitDlg->getExitCode();
+    if (exitCode == 0)
+      retStatus = true;
+    else  {
+      errorString =
+       QString(tr("Process exited unsucessfully with code %1"))
+       .arg(exitCode);
+      retStatus = false;
+    }
+  }
+  else {
+    retStatus = false;
+    errorString = waitDlg->getErrorString();
+  }
+  outputString = waitDlg->getOutputString();
+  delete proc;
+  delete waitDlg;
+  return retStatus;
+}
+
+//------------------------------------------------------------------------
+int MainWindow::formatIndexFromName(bool isFile, const QString &nm)
+{
+  for (int i= 0; i<formatList.size(); i++) {
+    if (nm == formatList[i].getName() && formatList[i].isFileFormat() == isFile)
+      return i;
+  }
+  return 0;
+}
+
+//------------------------------------------------------------------------
+QString MainWindow::charSetFromCombo(QComboBox *combo)
+{
+  int i = combo->itemData((combo->currentIndex())).toInt();
+  return (i >=0 ) ? charSets[i] : QString();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::setComboToCharSet(QComboBox *combo, const QString &cset)
+{
+  for (int i=0; i<charSets.size(); i++) {
+    if (charSets[i] == cset) {
+      combo->setCurrentIndex(i+1); // first index is default;
+    }
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::applyActionX()
+{
+  getWidgetValues();
+  if (!isOkToGo())
+    return;
+
+  QStringList args;
+
+  if (bd.debugLevel >=0)     args << QString("-D%1").arg(bd.debugLevel);
+  if (bd.synthShortNames)    args << "-s";
+
+  // Input char set if specified
+  if (bd.enableCharSetXform && bd.inputCharSet != QString())
+    args << "-c" << bd.inputCharSet;
+
+  Format ifmt = formatList[currentComboFormatIndex(ui.inputFormatCombo)];
+  Format ofmt = formatList[currentComboFormatIndex(ui.outputFormatCombo)];
+
+  if (bd.xlateWayPts && ifmt.isReadWaypoints() && ofmt.isWriteWaypoints())
+    args << "-w";
+  if (bd.xlateRoutes && ifmt.isReadRoutes()    && ofmt.isWriteRoutes())
+    args << "-r";
+  if (bd.xlateTracks && ifmt.isReadTracks()    && ofmt.isWriteTracks())
+    args << "-t";
+
+  // Input type, with options
+  bool iisFile = (bd.inputType == BabelData::fileType);
+  int fidx = formatIndexFromName(iisFile, iisFile ?
+                                bd.inputFileFormat : bd.inputDeviceFormat);
+  args << "-i";
+  args << (formatList[fidx].getName() + MakeOptions(formatList[fidx].getInputOptions()));
+
+  // Input file(s) or device
+  int read_use_count = 0;
+  if (bd.inputType == BabelData::fileType) {
+    for (int i=0; i<bd.inputFileNames.size(); i++) {
+      args << "-f" << bd.inputFileNames[i];
+      read_use_count++;
+    }
+  }
+  else {
+    args << "-f" << bd.inputDeviceName;
+    read_use_count++;
+  }
+  formatList[fidx].bumpReadUseCount(read_use_count);
+
+  // --- Filters!
+  args << filterData.getAllFilterStrings();
+
+  // Output char set if specified
+  if (bd.enableCharSetXform && bd.outputCharSet != QString())
+    args << "-c" << bd.outputCharSet;
+
+  // Output type, with options
+  if (bd.outputType != BabelData::noType) {
+    bool outIsFile = (bd.outputType == BabelData::fileType);
+    fidx = formatIndexFromName(outIsFile, (outIsFile ?
+                                          bd.outputFileFormat : bd.outputDeviceFormat));
+    args << "-o";
+    args << (formatList[fidx].getName() + MakeOptions(formatList[fidx].getOutputOptions()));
+
+    // output file or device option
+    if (outIsFile) {
+      if (bd.outputFileName != "")
+             args << "-F" << bd.outputFileName;
+    }
+    else if (bd.outputType == BabelData::deviceType) {
+      args << "-F" << bd.outputDeviceName;
+    }
+    // GUI only ever writes a single file at a time.
+    formatList[fidx].bumpWriteUseCount(1);
+  }
+
+  // Now output for preview in google maps
+  QString tempName;
+  if (bd.previewGmap) {
+    QTemporaryFile ftemp;
+    ftemp.open();
+    tempName = ftemp.fileName();
+    ftemp.close();
+
+    // Ideally, expost this in the UI.  For now, just split the track
+    // if we've no recorded fixes for > 5 mins and we've moved > 300 meters.
+    //args << "-x";
+    //args << "track,pack,sdistance=0.3k,split=5m";
+
+    args << "-o";
+    args << "gpx";
+    args << "-F" << tempName;
+  }
+
+  ui.outputWindow->clear();
+  ui.outputWindow->appendPlainText("gpsbabel " + args.join(" "));
+
+  QString errorString, outputString;
+  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  bool x = runGpsbabel(args, errorString, outputString);
+  QApplication::restoreOverrideCursor();
+
+  ui.outputWindow->appendPlainText(outputString);
+  if (x) {
+    ui.outputWindow->appendPlainText(tr("Translation successful"));
+    if (bd.previewGmap) {
+      this->hide();
+      GMapDialog dlg(0, tempName, bd.debugLevel >=1 ? ui.outputWindow : 0);
+      dlg.show();
+      dlg.exec();
+      this->show();
+    }
+  }
+  else
+    ui.outputWindow->appendPlainText(tr("Error running gpsbabel: %1\n").arg(errorString));
+}
+
+//------------------------------------------------------------------------
+void MainWindow::closeActionX()
+{
+  QDateTime wt= upgrade->getUpgradeWarningTime();
+  if (wt.isValid()) {
+    bd.upgradeCheckTime = wt;
+  }
+  bd.runCount++;
+
+  QDateTime now = QDateTime::currentDateTime();
+  if ((bd.runCount > 5) && (bd.donateSplashed.daysTo(now) > 30)) {
+    Donate donate(0);
+    if (bd.donateSplashed.date() == QDate(2010,1,1))
+      donate.showNever(false);
+    donate.exec();
+    bd.donateSplashed = now;
+  }
+  saveSettings();
+  delete upgrade;
+  upgrade = 0;
+  qApp->exit(0);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::closeEvent(QCloseEvent*)
+{
+  closeActionX();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::donateActionX()
+{
+  QDesktopServices::openUrl(QString("http://www.gpsbabel.org/contribute.html?gbversion=" VERSION));
+}
+
+//------------------------------------------------------------------------
+void MainWindow::visitWebsiteActionX()
+{
+  QDesktopServices::openUrl(QString("http://www.gpsbabel.org"));
+}
+
+//------------------------------------------------------------------------
+void MainWindow::dragEnterEvent(QDragEnterEvent *event)
+{
+  event->acceptProposedAction();
+}
+
+void MainWindow::dropEvent(QDropEvent *event)
+{
+  foreach (QString format, event->mimeData()->formats()) {
+    if (format == "text/uri-list") {
+      QList<QUrl> urlList = event->mimeData()->urls();
+      bd.inputFileNames.clear();
+      for (int i = 0; i < urlList.size(); ++i) {
+        QFileInfo file_info(urlList.at(i).path());
+        QString name = file_info.filePath();
+        QString ext = file_info.suffix();
+
+        QString fmt = getFormatNameForExtension(ext);
+        setComboToFormat(ui.inputFormatCombo, fmt, true);
+        ui.inputFileNameText->setText(name);
+        bd.inputFileNames << ui.inputFileNameText->text();
+        event->acceptProposedAction();
+      }
+    }
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::setComboToDevice(QComboBox *comboBox, const QString &name)
+{
+  for (int i=0; i<comboBox->count(); i++) {
+    if (comboBox->itemText(i) == name) {
+      comboBox->setCurrentIndex(i);
+      break;
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::saveSettings()
+{
+  getWidgetValues();
+
+  QSettings settings;
+  bd.saveSettings(settings);
+  for (int i=0; i<formatList.size(); i++)
+    formatList[i].saveSettings(settings);
+  for (int i=0; i<filterData.filters.size(); i++)
+    filterData.filters[i]->saveSettings(settings);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::restoreSettings()
+{
+  QSettings settings;
+  bd.restoreSettings(settings);
+  for (int i=0; i<formatList.size(); i++)
+    formatList[i].restoreSettings(settings);
+
+  for (int i=0; i<filterData.filters.size(); i++)
+    filterData.filters[i]->restoreSettings(settings);
+
+  setWidgetValues();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::resetFormatDefaults()
+{
+  int ret = QMessageBox::warning
+    (this, QString(appName),
+     tr("Are you sure you want to reset all format options to default values?"),
+     QMessageBox::Yes | QMessageBox::No);
+  if (ret == QMessageBox::Yes) {
+    for (int i=0; i<formatList.size(); i++)
+      formatList[i].setToDefault();
+    displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+    displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::moreOptionButtonClicked()
+{
+  AdvDlg advDlg(0, bd.synthShortNames,
+               bd.enableCharSetXform, bd.previewGmap, bd.debugLevel);
+  connect(advDlg.formatButton(), SIGNAL(clicked()),
+         this, SLOT(resetFormatDefaults()));
+  advDlg.exec();
+  checkCharSetCombos();
+}
+//------------------------------------------------------------------------
+void MainWindow::aboutActionX()
+{
+  AboutDlg aboutDlg(0, babelVersion, QString(appName) + QString(" " VERSION));
+  aboutDlg.setWindowTitle(tr("About %1").arg(appName));
+  aboutDlg.exec();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::upgradeCheckActionX()
+{
+    upgrade->checkForUpgrade(babelVersion, 
+                            QDateTime(QDate(2000, 1, 1), QTime(0, 0)), 
+                            allowBetaUpgrades());
+}
+
+//------------------------------------------------------------------------
+void MainWindow::preferencesActionX()
+{
+  Preferences preferences(0, formatList, bd);
+  preferences.exec();
+
+  // We may have changed the list of displayed formats.  Resynchronize.
+  setWidgetValues();
+}
+
+
+//------------------------------------------------------------------------
+void MainWindow::helpActionX()
+{
+  ShowHelp("index.html");
+}
+//------------------------------------------------------------------------
+void MainWindow::filtersClicked()
+{
+  FilterDialog dlg(0, filterData);
+  dlg.runDialog();
+  updateFilterStatus();
+}
+
+
+//------------------------------------------------------------------------
+void MainWindow::updateFilterStatus()
+{
+  bool filterActive = filterData.getAllFilterStrings().size();
+  ui.filterStatus->setEnabled(filterActive);
+  if (filterActive)
+    ui.filterStatus->setToolTip(tr("One or more data filters are active"));
+  else {
+    ui.filterStatus->setToolTip(tr("No data filters are active"));
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::setWidgetValues()
+{
+  if (bd.inputType == BabelData::fileType) {
+    ui.inputFileOptBtn->setChecked(true);
+    inputFileOptBtnClicked();
+    setComboToFormat(ui.inputFormatCombo, bd.inputFileFormat, true);
+    ui.inputStackedWidget->setCurrentWidget(ui.inputFilePage);
+  }
+  else {
+    ui.inputDeviceOptBtn->setChecked(true);
+    inputDeviceOptBtnClicked();
+    setComboToFormat(ui.inputFormatCombo, bd.inputDeviceFormat, false);
+    loadInputDeviceNameCombo(bd.inputDeviceFormat);
+    ui.inputStackedWidget->setCurrentWidget(ui.inputDevicePage);
+  }
+  setComboToDevice(ui.inputDeviceNameCombo, bd.inputDeviceName);
+  setComboToCharSet(ui.inputCharSetCombo, bd.inputCharSet);
+
+  if (bd.outputType == BabelData::fileType) {
+    ui.outputFileOptBtn->setChecked(true);
+    outputFileOptBtnClicked();
+    setComboToFormat(ui.outputFormatCombo, bd.outputFileFormat, true);
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+  }
+  else if (bd.outputType == BabelData::deviceType) {
+    ui.outputDeviceOptBtn->setChecked(true);
+    outputDeviceOptBtnClicked();
+    setComboToFormat(ui.outputFormatCombo, bd.outputDeviceFormat, false);
+    loadOutputDeviceNameCombo(bd.outputDeviceFormat);
+    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
+  }
+  else {
+    ui.outputFileOptBtn->setChecked(false);
+    ui.outputDeviceOptBtn->setChecked(false);
+    setComboToFormat(ui.outputFormatCombo, bd.outputFileFormat, true);
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+    ui.outputFilePage->setDisabled(true);
+  }
+
+  setComboToDevice(ui.outputDeviceNameCombo, bd.outputDeviceName);
+  setComboToCharSet(ui.outputCharSetCombo, bd.outputCharSet);
+
+  ui.xlateWayPtsCk->setChecked(bd.xlateWayPts);
+  ui.xlateTracksCk->setChecked(bd.xlateTracks);
+  ui.xlateRoutesCk->setChecked(bd.xlateRoutes);
+
+  crossCheckInOutFormats();
+  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+  checkCharSetCombos();
+  updateFilterStatus();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::getWidgetValues()
+{
+  int comboIdx = ui.inputFormatCombo->currentIndex();
+  int fidx = ui.inputFormatCombo->itemData(comboIdx).toInt();
+  if (ui.inputFileOptBtn->isChecked()){
+    bd.inputType = BabelData::fileType;
+    bd.inputFileFormat =formatList[fidx].getName();
+  }
+  else {
+    bd.inputType = BabelData::deviceType;
+    bd.inputDeviceFormat =formatList[fidx].getName();
+  }
+  bd.inputDeviceName = ui.inputDeviceNameCombo->currentText();
+  bd.inputCharSet = charSetFromCombo(ui.inputCharSetCombo);
+
+  comboIdx = ui.outputFormatCombo->currentIndex();
+  fidx = ui.outputFormatCombo->itemData(comboIdx).toInt();
+  if (ui.outputFileOptBtn->isChecked()){
+    bd.outputType = BabelData::fileType;
+    bd.outputFileFormat =formatList[fidx].getName();
+  }
+  else if (ui.outputDeviceOptBtn->isChecked()){
+    bd.outputType = BabelData::deviceType;
+    bd.outputDeviceFormat =formatList[fidx].getName();
+  }
+  else {
+    bd.outputType = BabelData::noType;
+  }
+  bd.outputDeviceName = ui.outputDeviceNameCombo->currentText();
+  bd.outputCharSet = charSetFromCombo(ui.outputCharSetCombo);
+
+  bd.xlateWayPts = ui.xlateWayPtsCk->isChecked();
+  bd.xlateTracks = ui.xlateTracksCk->isChecked();
+  bd.xlateRoutes = ui.xlateRoutesCk->isChecked();
+}
+
+// This could be made faster, but any attempt to do so would have to be
+// careful about disabled formats.  As it was written to be handled by a
+// drag response, performance is hardly critical.
+// It's also kind of dumb to return the name which SetCombo then looks up,
+// but there's not a 1:1 correlation between offsets in the combo box and
+// in the list of formats.
+QString MainWindow::getFormatNameForExtension(QString ext)
+{
+  for (int i = 0; i < formatList.size(); i++) {
+    QStringList extensions = formatList[i].getExtensions();
+    for (int j = 0; j < extensions.size(); ++j) {
+      if (extensions[j] == ext) {
+        return formatList[i].getName();;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/gpsbabel/gui/mainwindow.cpp b/gpsbabel/gui/mainwindow.cpp
deleted file mode 100644 (file)
index cbf30fb..0000000
+++ /dev/null
@@ -1,1350 +0,0 @@
-// -*- C++ -*-
-// $Id: mainwindow.cpp,v 1.27 2010-11-01 03:30:42 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-#include <QDesktopServices>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QMimeData>
-#include <QProcess>
-#include <QSettings>
-#include <QTemporaryFile>
-#include <QTextStream>
-
-#include "mainwindow.h"
-#include "../gbversion.h"
-#include "aboutdlg.h"
-#include "advdlg.h"
-#include "appname.h"
-#include "babeldata.h"
-#include "donate.h"
-#include "filterdlg.h"
-#include "formatload.h"
-#include "gmapdlg.h"
-#include "help.h"
-#include "optionsdlg.h"
-#include "preferences.h"
-#include "processwait.h"
-#include "version_mismatch.h"
-#include "upgrade.h"
-
-const int BabelData::noType = -1;
-const int BabelData::fileType = 0;
-const int BabelData::deviceType = 1;
-
-#define FAKE_LANGUAGE_MENU 0
-
-//------------------------------------------------------------------------
-QString MainWindow::findBabelVersion()
-{
-  QProcess babel;
-  babel.start("gpsbabel", QStringList() << "-V");
-  if (!babel.waitForStarted())
-    return QString();
-  babel.closeWriteChannel();
-  if (!babel.waitForFinished())
-    return QString();
-
-  QString str = babel.readAll();
-  is_beta = str.contains("-beta");
-  str.replace("Version",  "");
-  str.replace("GPSBabel",  "");
-  str.replace(QRegExp("^[\\s]*"),  "");
-  str.replace(QRegExp("[\\s]+$"),  "");
-  str = str.simplified();
-  return str;
-}
-
-//------------------------------------------------------------------------
-// Decides whether available beta upgrades are suggested to user for download.
-bool MainWindow::allowBetaUpgrades()
-{
-  // If this is a beta version (which means the user consciously downloaded
-  // it and decided to be on the beta track or the user has ticked the 
-  // 'suggest beta upgrade' box, allow betas to be suggested for installation.
-  return is_beta || bd.allowBetaUpgrades;
-}
-
-//------------------------------------------------------------------------
-static QStringList getCharSets()
-{
-  QProcess babel;
-  babel.start("gpsbabel", QStringList() << "-l");
-  if (!babel.waitForStarted())
-    return QStringList();
-  babel.closeWriteChannel();
-  if (!babel.waitForFinished())
-    return QStringList();
-
-  QStringList strList;
-  QTextStream tstream(babel.readAll());
-  while(!tstream.atEnd()) {
-    QString l = tstream.readLine();
-    if (QRegExp("^\\*").indexIn(l) == 0) {
-      l.replace(QRegExp("^[\\*\\s]*"),  "");
-      l.replace(QRegExp("[\\s]+$"),  "");
-      strList << l;
-    }
-  }
-  return strList;
-}
-
-//------------------------------------------------------------------------
-static QString MakeOptions(const QList<FormatOption>& options)
-{
-  QString str;
-  for (int i=0; i<options.size(); i++) {
-    if (options[i].getSelected()) {
-      str += ",";
-      str += options[i].getName();
-      if (options[i].getType() == FormatOption::OPTbool) {
-        str += "=1";
-      } else {
-        str += "=" + options[i].getValue().toString();
-      }
-    } else {
-      if (options[i].getType() == FormatOption::OPTbool) {
-        str += "," + options[i].getName() + "=0";
-      }
-    }
-  }
-  return str;
-}
-
-//------------------------------------------------------------------------
-static QString MakeOptionsNoLeadingComma(const QList<FormatOption>& options)
-{
-  QString str = MakeOptions(options);
-  return (str.length()) ? str.mid(1) : str;
-
-}
-
-//------------------------------------------------------------------------
-MainWindow::MainWindow(QWidget* parent): QMainWindow(parent)
-{
-  loadFormats();
-  ui.setupUi(this);
-  setWindowTitle(appName);
-  babelVersion = findBabelVersion();
-  fmtChgInterlock = false;
-  loadDeviceNameCombos();
-  loadCharSetCombos();
-
-  connect(ui.inputFileOptBtn,        SIGNAL(clicked()), this, SLOT(inputFileOptBtnClicked()));
-  connect(ui.inputDeviceOptBtn,      SIGNAL(clicked()), this, SLOT(inputDeviceOptBtnClicked()));
-  connect(ui.inputFileNameBrowseBtn, SIGNAL(clicked()), this, SLOT(browseInputFile()));
-
-  ui.outputFileOptBtn->setAutoExclusive(false);
-  ui.outputDeviceOptBtn->setAutoExclusive(false);
-  connect(ui.outputFileOptBtn,        SIGNAL(clicked()), this, SLOT(outputFileOptBtnClicked()));
-  connect(ui.outputDeviceOptBtn,      SIGNAL(clicked()), this, SLOT(outputDeviceOptBtnClicked()));
-  connect(ui.outputFileNameBrowseBtn, SIGNAL(clicked()), this, SLOT(browseOutputFile()));
-
-  connect(ui.actionQuit, SIGNAL(triggered()), this, SLOT(closeActionX()));
-  connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(helpActionX()));
-  connect(ui.actionAbout, SIGNAL(triggered()), this, SLOT(aboutActionX()));
-  connect(ui.actionVisit_Website, SIGNAL(triggered()), this, SLOT(visitWebsiteActionX()));
-  connect(ui.actionMake_a_Donation, SIGNAL(triggered()), this, SLOT(donateActionX()));
-  connect(ui.actionUpgradeCheck, SIGNAL(triggered()), this, SLOT(upgradeCheckActionX()));
-  connect(ui.actionPreferences, SIGNAL(triggered()), this, SLOT(preferencesActionX()));
-
-  connect(ui.inputFormatCombo,  SIGNAL(currentIndexChanged(int)),
-         this,                 SLOT(inputFormatChanged(int)));
-  connect(ui.outputFormatCombo, SIGNAL(currentIndexChanged(int)),
-         this,                 SLOT(outputFormatChanged(int)));
-  connect(ui.inputOptionsBtn,   SIGNAL(clicked()),
-         this,                 SLOT(inputOptionButtonClicked()));
-  connect(ui.outputOptionsBtn , SIGNAL(clicked()),
-         this,                 SLOT(outputOptionButtonClicked()));
-  connect(ui.moreOptionButton , SIGNAL(clicked()),
-         this,                 SLOT(moreOptionButtonClicked()));
-
-  connect(ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyActionX()));
-  connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(closeActionX()));
-  connect(ui.xlateFiltersBtn, SIGNAL(clicked()), this, SLOT(filtersClicked()));
-
-  connect(ui.inputFileNameText, SIGNAL(textEdited(QString)), this, SLOT(inputFileNameEdited()));
-  connect(ui.outputFileNameText, SIGNAL(textEdited(QString)), this, SLOT(outputFileNameEdited()));
-
-
-  ui.buttonBox->button(QDialogButtonBox::Apply)->setIcon(QIcon(":images/runit.png"));
-  ui.buttonBox->button(QDialogButtonBox::Close)->setIcon(QIcon(":images/exit.png"));
-
-
-  ui.inputOptionsText->setReadOnly(true);
-  ui.outputOptionsText->setReadOnly(true);
-#if 0
-  // 02/28/10  - let's try letting people edit these outside the browse.
-  ui.inputFileNameText->setReadOnly(true);
-  ui.outputFileNameText->setReadOnly(true);
-#else
-  setAcceptDrops(true);
-#endif
-  ui.wayPtLabel->setText("");
-  ui.trackLabel->setText("");
-  ui.routeLabel->setText("");
-  lights[0] = QPixmap::fromImage(QImage(":images/00.png").scaledToHeight(20, Qt::SmoothTransformation));
-  lights[1] = QPixmap::fromImage(QImage(":images/01.png").scaledToHeight(20, Qt::SmoothTransformation));
-  lights[2] = QPixmap::fromImage(QImage(":images/10.png").scaledToHeight(20, Qt::SmoothTransformation));
-  lights[3] = QPixmap::fromImage(QImage(":images/11.png").scaledToHeight(20, Qt::SmoothTransformation));
-
-  ui.outputWindow->setReadOnly(true);
-
-  langPath = QApplication::applicationDirPath();
-  langPath.append("/translations/");
-
-  // Start up in the current system language.
-  loadLanguage(QLocale::system().name());
-#if FAKE_LANGUAGE_MENU
-  createLanguageMenu();
-#endif
-
-  //--- Restore from registry
-  restoreSettings();
-
-  upgrade = new UpgradeCheck(parent, formatList, bd);
-  if (bd.startupVersionCheck) {
-    upgrade->checkForUpgrade(babelVersion, bd.upgradeCheckTime, 
-                             allowBetaUpgrades());
-  }
-
-  if (!bd.ignoreVersionMismatch && babelVersion != VERSION) {
-    VersionMismatch vm(0, babelVersion, QString(VERSION));
-
-    vm.exec();
-    bd.ignoreVersionMismatch = vm.neverAgain();
-  }
-}
-
-//------------------------------------------------------------------------
-MainWindow::~MainWindow()
-{
-  if (upgrade)
-    delete upgrade;
-}
-//------------------------------------------------------------------------
-// Dynamic language switching courtesy of 
-// http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application
-// We create the menu entries dynamically, dependant on the existing 
-// translations.
-#if FAKE_LANGUAGE_MENU
-void MainWindow::createLanguageMenu(void)
-{
-    QActionGroup* langGroup = new QActionGroup(ui.menuHelp);
-    langGroup->setExclusive(true);
-    connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotLanguageChanged(QAction *)));
-
-    // format systems language
-    QString defaultLocale = QLocale::system().name();       // e.g. "de_DE"
-    defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de"
-
-    QDir dir(langPath);
-    QStringList fileNames = dir.entryList(QStringList("GPSBabelFE*.qm"));
-
-    for (int i = 0; i < fileNames.size(); ++i) {
-        // get locale extracted by filename
-        QString locale;
-        locale = fileNames[i];                  // "TranslationExample_de.qm"
-        locale.truncate(locale.lastIndexOf('.'));   // "TranslationExample_de"
-        locale.remove(0, locale.indexOf('_') + 1);   // "de"
-
-        QString lang = QLocale::languageToString(QLocale(locale).language());
-
-        QAction *action = new QAction(lang, this);
-        action->setCheckable(true);
-        action->setData(locale);
-
-        ui.menuHelp->addAction(action);
-        langGroup->addAction(action);
-
-        // set default translators and language checked
-        if (defaultLocale == locale) {
-            action->setChecked(true);
-        }
-    }
-}
-#endif //  FAKE_LANGUAGE_MENU
-
-//------------------------------------------------------------------------
-// Called every time, when a menu entry of the language menu is called
-void MainWindow::slotLanguageChanged(QAction* action)
-{
-  if (0 != action) {
-    // load the language dependant on the action content.
-    loadLanguage(action->data().toString());
-  }
-}
-
-void MainWindow::switchTranslator(QTranslator& translator, const QString& filename)
-{
-  // remove the old translator
-  qApp->removeTranslator(&translator);
-
-  QString full_filename(langPath + "/" + filename);
-
-  // load the new translator
-  if (translator.load(full_filename))
-    qApp->installTranslator(&translator);
-}
-
-void MainWindow::loadLanguage(const QString& rLanguage)
-{
-  if (currLang != rLanguage) {
-    currLang = rLanguage;
-    QLocale locale = QLocale(currLang);
-    QLocale::setDefault(locale);
-    QString languageName = QLocale::languageToString(locale.language());
-
-    switchTranslator(translator, QString("gpsbabelfe_%1.qm").arg(rLanguage));
-    switchTranslator(translatorCore, QString("gpsbabel__%1.qm").arg(rLanguage));
-    switchTranslator(translatorQt, QString("qt_%1.qm").arg(rLanguage));
-  }
-}
-
-void MainWindow::changeEvent(QEvent* event)
-{
-    if (0 != event) {
-        switch(event->type()) {
-        // This event is sent if a translator is loaded.
-        case QEvent::LanguageChange:
-            ui.retranslateUi(this);
-            break;
-        // This event is sent if the system language changes.
-        case QEvent::LocaleChange:
-            {
-                QString locale = QLocale::system().name();
-                locale.truncate(locale.lastIndexOf('_'));
-                loadLanguage(locale);
-            }
-           break;
-        default:
-           break;
-        }
-    }
-    QMainWindow::changeEvent(event);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::loadInputDeviceNameCombo(const QString &format)
-{
-  ui.inputDeviceNameCombo->clear();
-  // Later, we can probe the system for multiple USB devices and populate 
-  // here.
-  if (formatSupportsUSB(format))
-    ui.inputDeviceNameCombo->addItem("usb:");
-  if (formatSupportsSerial(format))
-    osLoadDeviceNameCombos(ui.inputDeviceNameCombo);
-  // If only one choice, just disable it.
-  ui.inputDeviceNameCombo->setEnabled(ui.inputDeviceNameCombo->count() > 1);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::loadOutputDeviceNameCombo(const QString &format)
-{
-  ui.outputDeviceNameCombo->clear();
-  // Later, we can probe the system for multiple USB devices and populate 
-  // here.
-  if (formatSupportsUSB(format))
-    ui.outputDeviceNameCombo->addItem("usb:");
-  if (formatSupportsSerial(format))
-    osLoadDeviceNameCombos(ui.outputDeviceNameCombo);
-  // If only one choice, just disable it.
-  ui.outputDeviceNameCombo->setEnabled(ui.outputDeviceNameCombo->count() > 1);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::loadDeviceNameCombos()
-{
-  loadInputDeviceNameCombo("");
-  loadOutputDeviceNameCombo("");
-}
-//------------------------------------------------------------------------
-void MainWindow::loadCharSetCombos()
-{
-  charSets = getCharSets();
-
-  ui.inputCharSetCombo->clear();
-  ui.outputCharSetCombo->clear();
-  ui.inputCharSetCombo->addItem(tr("default"), QVariant(-1));
-  ui.outputCharSetCombo->addItem(tr("default"), QVariant(-1));
-  for (int i=0; i<charSets.size(); i++) {
-    ui.inputCharSetCombo->addItem(charSets[i], QVariant(i));
-    ui.outputCharSetCombo->addItem(charSets[i], QVariant(i));
-  }
-}
-//------------------------------------------------------------------------
-void MainWindow::checkCharSetCombos()
-{
-  ui.inputCharSetCombo->setEnabled(bd.enableCharSetXform);
-  ui.outputCharSetCombo->setEnabled(bd.enableCharSetXform);
-  ui.inputCharSetCombo->setVisible(bd.enableCharSetXform);
-  ui.outputCharSetCombo->setVisible(bd.enableCharSetXform);
-}
-//------------------------------------------------------------------------
-void MainWindow::inputFileOptBtnClicked()
-{
-  fmtChgInterlock = true;
-  QString fmt = bd.inputFileFormat;
-  ui.inputStackedWidget->setCurrentWidget(ui.inputFilePage);
-  QList<int>indices = inputFileFormatIndices();
-  ui.inputFormatCombo->clear();
-  for (int i=0; i<indices.size(); i++) {
-    int k = indices[i];
-    if (!formatList[k].isHidden())
-      ui.inputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
-  }
-  setComboToFormat(ui.inputFormatCombo, fmt, true);
-  fmtChgInterlock = false;
-}
-
-//------------------------------------------------------------------------
-void MainWindow::inputDeviceOptBtnClicked()
-{
-  fmtChgInterlock = true;
-  QString fmt = bd.inputDeviceFormat;
-  ui.inputStackedWidget->setCurrentWidget(ui.inputDevicePage);
-  QList<int>indices = inputDeviceFormatIndices();
-  ui.inputFormatCombo->clear();
-  for (int i=0; i<indices.size(); i++) {
-    int k = indices[i];
-    if (!formatList[k].isHidden())
-      ui.inputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
-  }
-  setComboToFormat(ui.inputFormatCombo, fmt, false);
-  fmtChgInterlock = false;
-}
-
-//------------------------------------------------------------------------
-void MainWindow:: outputFileOptBtnClicked()
-{
-  fmtChgInterlock = true;
-  if (ui.outputFileOptBtn->isChecked()) {
-    ui.outputFilePage->setEnabled(true);
-    ui.outputDeviceOptBtn->setChecked(false);
-    QString fmt = bd.outputFileFormat;
-    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
-    QList<int>indices = outputFileFormatIndices();
-    ui.outputFormatCombo->clear();
-    for (int i=0; i<indices.size(); i++) {
-      int k = indices[i];
-      ui.outputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
-    }
-    setComboToFormat(ui.outputFormatCombo, fmt, true);
-  }
-  else {
-    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
-    ui.outputFilePage->setEnabled(false);
-  }
-  fmtChgInterlock = false;
-}
-
-//------------------------------------------------------------------------
-void MainWindow:: outputDeviceOptBtnClicked()
-{
-  fmtChgInterlock = true;
-  if (ui.outputDeviceOptBtn->isChecked()) {
-    ui.outputDevicePage->setEnabled(true);
-    ui.outputFileOptBtn->setChecked(false);
-    QString fmt = bd.outputDeviceFormat;
-    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
-    QList<int>indices = outputDeviceFormatIndices();
-    ui.outputFormatCombo->clear();
-    for (int i=0; i<indices.size(); i++) {
-      int k = indices[i];
-      ui.outputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
-    }
-    setComboToFormat(ui.outputFormatCombo, fmt, false);
-  }
-  else {
-    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
-    ui.outputDevicePage->setEnabled(false);
-  }
-  fmtChgInterlock = false;
-}
-void MainWindow::inputFileNameEdited()
-{
-  bd.inputFileNames.clear();
-  bd.inputFileNames << ui.inputFileNameText->text();
-}
-
-void MainWindow::outputFileNameEdited()
-{
-  bd.outputFileName = ui.outputFileNameText->text();
-
-}
-
-//------------------------------------------------------------------------
-QString MainWindow::filterForFormat(int idx)
-{
-  QString str = formatList[idx].getDescription();
-  str.replace(QRegExp("\\("), "[");
-  str.replace(QRegExp("\\)"), "]");
-  QStringList extensions = formatList[idx].getExtensions();
-
-  // If we don't have any meaningful extensions available for this format,
-  // don't be clever here; just fall through to "All files" case.
-  if (extensions.size() > 0 && !extensions[0].isEmpty()) {
-    str += " (";
-    for (int i=0; i<extensions.size(); i++) {
-      if (i!= 0)
-        str += " ";
-      str += "*." + extensions[i];
-    }
-    str += ");;";
-  }
-  str += "All Files (*.*)";
-  return str;
-}
-//------------------------------------------------------------------------
-QString MainWindow::ensureExtensionPresent(const QString &name, int idx)
-{
-  QString outname = name;
-  if (QFileInfo(name).suffix().length() == 0) {
-    QStringList extensions = formatList[idx].getExtensions();
-    if (extensions.size() > 0)
-      outname += "." + extensions[0];
-  }
-  return outname;
-}
-
-//------------------------------------------------------------------------
-bool MainWindow::filterForFormatIncludes(int idx, const QString &fmt)
-{
-  QStringList extensions = formatList[idx].getExtensions();
-  for (int i=0; i<extensions.size(); i++) {
-    if (fmt == extensions[i])
-      return true;
-  }
-  return false;
-}
-
-//------------------------------------------------------------------------
-int MainWindow::currentComboFormatIndex(QComboBox *comboBox)
-{
-  int idx = comboBox->currentIndex();
-  if (idx<0 || idx >= comboBox->count()) {
-    //    QMessageBox::critical(0, appName, "*** Internal Error -- current combo index is invalid!");
-    return 0;
-  }
-  return comboBox->itemData(idx).toInt();
-}
-//------------------------------------------------------------------------
-void MainWindow::browseInputFile()
-{
-  QString startFile = bd.inputFileNames.size() ? bd.inputFileNames[0] : bd.inputBrowse;
-  int idx = currentComboFormatIndex(ui.inputFormatCombo);
-  QFileInfo finfo(startFile);
-  if (!finfo.isDir() && (!filterForFormatIncludes(idx, finfo.suffix()))) {
-    startFile = finfo.dir().absolutePath();
-  }
-
-  QStringList userList =
-    QFileDialog::getOpenFileNames(0, tr("Select one or more input files"),
-                                 startFile,
-                                 filterForFormat(idx));
-  if (userList.size()) {
-    bd.inputBrowse = userList[0];
-    bd.inputFileNames = userList;
-    QString str;
-    for (int i=0; i<bd.inputFileNames.size(); i++) {
-      if (i != 0)
-        str += ", ";
-      str += "\"" + bd.inputFileNames[i] + "\"";
-    }
-    ui.inputFileNameText->setText(str);
-  }
-}
-
-//------------------------------------------------------------------------
-void MainWindow::browseOutputFile()
-{
-  int idx = currentComboFormatIndex(ui.outputFormatCombo);
-  QString startFile = bd.outputFileName.length() == 0 ? bd.outputBrowse : bd.outputFileName;
-  QFileInfo finfo(startFile);
-  if (!finfo.isDir() && (!filterForFormatIncludes(idx, finfo.suffix()))) {
-    startFile = finfo.dir().absolutePath();
-  }
-
-  QString str =
-    QFileDialog::getSaveFileName(0, tr("Output File Name"),
-                                startFile,
-                                filterForFormat(idx));
-  if (str.length() != 0) {
-    str = ensureExtensionPresent(str, idx);
-    bd.outputBrowse = str;
-    bd.outputFileName = str;
-    ui.outputFileNameText->setText(str);
-  }
-}
-
-//------------------------------------------------------------------------
-QList<int> MainWindow::inputFileFormatIndices()
-{
-  QList<int>indices;
-  for (int i=0; i<formatList.size(); i++) {
-    if (formatList[i].isReadSomething() && formatList[i].isFileFormat())
-      indices<<i;
-  }
-  return indices;
-}
-
-//------------------------------------------------------------------------
-QList<int> MainWindow::inputDeviceFormatIndices()
-{
-  QList<int>indices;
-  for (int i=0; i<formatList.size(); i++) {
-    if (formatList[i].isReadSomething() && formatList[i].isDeviceFormat())
-      indices<<i;
-  }
-  return indices;
-}
-
-//------------------------------------------------------------------------
-QList<int> MainWindow::outputFileFormatIndices()
-{
-  QList<int>indices;
-  for (int i=0; i<formatList.size(); i++) {
-    if (formatList[i].isWriteSomething() && formatList[i].isFileFormat())
-      indices<<i;
-  }
-  return indices;
-}
-
-//------------------------------------------------------------------------
-QList<int> MainWindow::outputDeviceFormatIndices()
-{
-  QList<int>indices;
-  for (int i=0; i<formatList.size(); i++) {
-    if (formatList[i].isWriteSomething() && formatList[i].isDeviceFormat())
-      indices<<i;
-  }
-  return indices;
-}
-
-//------------------------------------------------------------------------
-void MainWindow::loadFormats()
-{
-  if (!FormatLoad().getFormats(formatList)) {
-    QMessageBox::information(0, QString(appName),
-                            tr("Error reading format configuration.  "
-                               "Check that the backend program \"gpsbabel\" is properly installed "
-                               "and is in the current PATH\n\n"
-                               "This program cannot continue."));
-   exit(1);
-  }
-  if (inputFileFormatIndices().size() == 0 ||
-      inputDeviceFormatIndices().size() == 0 ||
-      outputFileFormatIndices().size() == 0 ||
-      outputDeviceFormatIndices().size() == 0) {
-    QMessageBox::information(0, QString(appName),
-                            tr("Some file/device formats were not found during initialization.  "
-                               "Check that the backend program \"gpsbabel\" is properly installed "
-                               "and is in the current PATH\n\n"
-                               "This program cannot continue."));
-    exit(1);
-  }
-}
-//------------------------------------------------------------------------
-static int iconIndex(bool a, bool b)
-{
-  return ((a?1:0)*2) + (b?1:0);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::setIndicatorLights(QLabel *label, const QString &type, int code)
-{
-  label->setPixmap(lights[code]);
-  QString s;
-  switch (code)
-    {
-    default:
-    case 0:
-      s = tr("Input and output formats do not support %1").arg(type);
-      break;
-    case 1:
-      s = tr("Input does not support %1; output format supports %2").arg(type).arg(type);
-      break;
-    case 2:
-      s = tr("Input format supports %1; output format does not support %2").arg(type).arg(type);
-      break;
-    case 3:
-      s = tr("Both input and output formats support %1").arg(type);
-      break;
-    }
-  label->setToolTip(s);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::crossCheckInOutFormats()
-{
-  if (ui.inputFormatCombo->count() == 0 ||
-      ui.outputFormatCombo->count() == 0) {
-    // During format/device switch this is true
-    return;
-  }
-  Format ifmt = formatList[currentComboFormatIndex(ui.inputFormatCombo)];
-  Format ofmt = formatList[currentComboFormatIndex(ui.outputFormatCombo)];
-
-  ui.xlateWayPtsCk->setEnabled(ifmt.isReadWaypoints() && ofmt.isWriteWaypoints());
-  ui.xlateTracksCk->setEnabled(ifmt.isReadTracks()    && ofmt.isWriteTracks());
-  ui.xlateRoutesCk->setEnabled(ifmt.isReadRoutes()    && ofmt.isWriteRoutes());
-
-  setIndicatorLights(ui.wayPtLabel, tr("waypoints"), iconIndex(ifmt.isReadWaypoints(), ofmt.isWriteWaypoints()));
-  setIndicatorLights(ui.trackLabel, tr("tracks"), iconIndex(ifmt.isReadTracks(), ofmt.isWriteTracks()));
-  setIndicatorLights(ui.routeLabel, tr("routes"), iconIndex(ifmt.isReadRoutes(), ofmt.isWriteRoutes()));
-}
-
-//------------------------------------------------------------------------
-void MainWindow::displayOptionsText(QLineEdit *le, QComboBox *combo, bool isInput)
-{
-  int fidx = combo->itemData(combo->currentIndex()).toInt();
-  if (isInput)
-    le->setText(MakeOptionsNoLeadingComma(formatList[fidx].getInputOptions()));
-  else
-    le->setText(MakeOptionsNoLeadingComma(formatList[fidx].getOutputOptions()));
-
-}
-
-//------------------------------------------------------------------------
-void MainWindow::setComboToFormat(QComboBox *comboBox, const QString &name, bool isFile)
-{
-  int fidx = -1;
-  for (int i=0; i<formatList.size(); i++) {
-    if (formatList[i].getName() == name &&
-       formatList[i].isFileFormat() == isFile) {
-      fidx = i;
-      break;
-    }
-  }
-  if (fidx >=0) {
-    for (int i=0; i<comboBox->count(); i++) {
-      if (comboBox->itemData(i).toInt() == fidx) {
-       comboBox->setCurrentIndex(i);
-       break;
-      }
-    }
-  }
-}
-
-//------------------------------------------------------------------------
-bool MainWindow::formatSupportsUSB(const QString &format)
-{
-    return (format == "garmin" || format == "delbin");
-}
-
-//------------------------------------------------------------------------
-bool MainWindow::formatSupportsSerial(const QString &format)
-{
-    return (format != "delbin");
-}
-
-//------------------------------------------------------------------------
-void MainWindow::inputFormatChanged(int comboIdx)
-{
-  if (fmtChgInterlock)
-    return;
-  int fidx = ui.inputFormatCombo->itemData(comboIdx).toInt();
-  ui.inputOptionsBtn->setEnabled(formatList[fidx].getInputOptions().size()>0);
-  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
-  crossCheckInOutFormats();
-
-  if (ui.inputFileOptBtn->isChecked())
-    bd.inputFileFormat =formatList[fidx].getName();
-  else
-    bd.inputDeviceFormat = formatList[fidx].getName();
-
-  loadInputDeviceNameCombo(formatList[fidx].getName());
-}
-
-//------------------------------------------------------------------------
-void MainWindow::outputFormatChanged(int comboIdx)
-{
-  if (fmtChgInterlock)
-    return;
-  int fidx = ui.outputFormatCombo->itemData(comboIdx).toInt();
-  ui.outputOptionsBtn->setEnabled(formatList[fidx].getOutputOptions().size()>0);
-  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
-  crossCheckInOutFormats();
-
-  if (ui.outputFileOptBtn->isChecked())
-    bd.outputFileFormat =formatList[fidx].getName();
-  else if (ui.outputDeviceOptBtn->isChecked())
-    bd.outputDeviceFormat = formatList[fidx].getName();
-
-  loadOutputDeviceNameCombo(formatList[fidx].getName());
-}
-
-//------------------------------------------------------------------------
-void MainWindow::inputOptionButtonClicked()
-{
-  int fidx = currentComboFormatIndex(ui.inputFormatCombo);
-  if (formatList[fidx].getInputOptionsRef()->size() == 0) {
-    QMessageBox::information
-      (0, appName,
-       tr("There are no input options for format \"%1\"").arg(formatList[fidx].getDescription()));
-  }
-  else {
-    OptionsDlg optionDlg(0,
-                        formatList[fidx].getName(),
-                        formatList[fidx].getInputOptionsRef(),
-                        formatList[fidx].getHtml());
-    optionDlg.setWindowTitle(QString(appName) + " - " + tr("Options for %1").arg(formatList[fidx].getName()));
-    optionDlg.exec();
-    displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
-  }
-}
-
-//------------------------------------------------------------------------
-void MainWindow::outputOptionButtonClicked()
-{
-  int fidx = currentComboFormatIndex(ui.outputFormatCombo);
-  if (formatList[fidx].getOutputOptionsRef()->size() == 0) {
-    QMessageBox::information
-      (0, appName,
-       tr("There are no output options for format \"%1\"").arg(formatList[fidx].getDescription()));
-  }
-  else {
-    OptionsDlg optionDlg(0, 
-                        formatList[fidx].getName(), 
-                        formatList[fidx].getOutputOptionsRef(),
-                        formatList[fidx].getHtml());
-    optionDlg.setWindowTitle(QString(appName) + " - " + tr("Options for %1").arg(formatList[fidx].getName()));
-    optionDlg.exec();
-    displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
-  }
-}
-
-
-
-//------------------------------------------------------------------------
-bool MainWindow::isOkToGo()
-{
-  if (!((ui.xlateWayPtsCk->isChecked() && ui.xlateWayPtsCk->isEnabled()) ||
-       (ui.xlateRoutesCk->isChecked() && ui.xlateRoutesCk->isEnabled()) ||
-       (ui.xlateTracksCk->isChecked() && ui.xlateTracksCk->isEnabled()))) {
-    QMessageBox::information(0, QString(appName), tr("No valid waypoints/routes/tracks translation specified"));
-    return false;
-  }
-
-  // Paper over what didn't happen in inputBrowse() if the user edited
-  // the filename fields directly.
-  if ((bd.inputType == BabelData::fileType) &&
-      (bd.inputFileNames.size() == 0) &&
-      (!ui.inputFileNameText->text().isEmpty())) {
-    bd.inputFileNames << ui.inputFileNameText->text();
-  }
-  if ((bd.outputType == BabelData::fileType) &&
-      (bd.outputFileName.size() == 0) &&
-      (!ui.outputFileNameText->text().isEmpty())) {
-    bd.outputFileName = ui.outputFileNameText->text();
-  }
-
-  if ((bd.inputType == BabelData::fileType) &&
-      (bd.inputFileNames.size() == 0)) {
-    QMessageBox::information(0, QString(appName), tr("No input file specified"));
-    return false;
-  }
-
-  if (bd.outputType == BabelData::noType && bd.previewGmap == true) {
-  }
-  if (bd.outputType == BabelData::noType && bd.previewGmap == false) {
-    QMessageBox::information(0, QString(appName), tr("No valid output specified"));
-    return false;
-  }
-  else if (bd.outputType == BabelData::fileType &&
-          bd.outputFileName.length() == 0) {
-    QMessageBox::information(0, QString(appName), tr("No output file specified"));
-    return false;
-  }
-  return true;
-}
-
-//------------------------------------------------------------------------
-bool MainWindow::runGpsbabel(const QStringList &args, QString &errorString,
-                         QString &outputString)
-{
-  QProcess *proc = new QProcess(0);
-  QString name = "gpsbabel";
-  proc->start(name, args);
-  ProcessWaitDialog *waitDlg = new ProcessWaitDialog(0, proc);
-
-  if (proc->state() == QProcess::NotRunning) {
-    errorString = QString(tr("Process \"%1\" did not start")).arg(name);
-    return false;
-  }
-
-  waitDlg->show();
-  waitDlg->exec();
-  int exitCode = -1;
-  bool retStatus = false;
-  if (waitDlg->getExitedNormally()) {
-    exitCode = waitDlg->getExitCode();
-    if (exitCode == 0)
-      retStatus = true;
-    else  {
-      errorString =
-       QString(tr("Process exited unsucessfully with code %1"))
-       .arg(exitCode);
-      retStatus = false;
-    }
-  }
-  else {
-    retStatus = false;
-    errorString = waitDlg->getErrorString();
-  }
-  outputString = waitDlg->getOutputString();
-  delete proc;
-  delete waitDlg;
-  return retStatus;
-}
-
-//------------------------------------------------------------------------
-int MainWindow::formatIndexFromName(bool isFile, const QString &nm)
-{
-  for (int i= 0; i<formatList.size(); i++) {
-    if (nm == formatList[i].getName() && formatList[i].isFileFormat() == isFile)
-      return i;
-  }
-  return 0;
-}
-
-//------------------------------------------------------------------------
-QString MainWindow::charSetFromCombo(QComboBox *combo)
-{
-  int i = combo->itemData((combo->currentIndex())).toInt();
-  return (i >=0 ) ? charSets[i] : QString();
-}
-
-//------------------------------------------------------------------------
-void MainWindow::setComboToCharSet(QComboBox *combo, const QString &cset)
-{
-  for (int i=0; i<charSets.size(); i++) {
-    if (charSets[i] == cset) {
-      combo->setCurrentIndex(i+1); // first index is default;
-    }
-  }
-}
-//------------------------------------------------------------------------
-void MainWindow::applyActionX()
-{
-  getWidgetValues();
-  if (!isOkToGo())
-    return;
-
-  QStringList args;
-
-  if (bd.debugLevel >=0)     args << QString("-D%1").arg(bd.debugLevel);
-  if (bd.synthShortNames)    args << "-s";
-
-  // Input char set if specified
-  if (bd.enableCharSetXform && bd.inputCharSet != QString())
-    args << "-c" << bd.inputCharSet;
-
-  Format ifmt = formatList[currentComboFormatIndex(ui.inputFormatCombo)];
-  Format ofmt = formatList[currentComboFormatIndex(ui.outputFormatCombo)];
-
-  if (bd.xlateWayPts && ifmt.isReadWaypoints() && ofmt.isWriteWaypoints())
-    args << "-w";
-  if (bd.xlateRoutes && ifmt.isReadRoutes()    && ofmt.isWriteRoutes())
-    args << "-r";
-  if (bd.xlateTracks && ifmt.isReadTracks()    && ofmt.isWriteTracks())
-    args << "-t";
-
-  // Input type, with options
-  bool iisFile = (bd.inputType == BabelData::fileType);
-  int fidx = formatIndexFromName(iisFile, iisFile ?
-                                bd.inputFileFormat : bd.inputDeviceFormat);
-  args << "-i";
-  args << (formatList[fidx].getName() + MakeOptions(formatList[fidx].getInputOptions()));
-
-  // Input file(s) or device
-  int read_use_count = 0;
-  if (bd.inputType == BabelData::fileType) {
-    for (int i=0; i<bd.inputFileNames.size(); i++) {
-      args << "-f" << bd.inputFileNames[i];
-      read_use_count++;
-    }
-  }
-  else {
-    args << "-f" << bd.inputDeviceName;
-    read_use_count++;
-  }
-  formatList[fidx].bumpReadUseCount(read_use_count);
-
-  // --- Filters!
-  args << filterData.getAllFilterStrings();
-
-  // Output char set if specified
-  if (bd.enableCharSetXform && bd.outputCharSet != QString())
-    args << "-c" << bd.outputCharSet;
-
-  // Output type, with options
-  if (bd.outputType != BabelData::noType) {
-    bool outIsFile = (bd.outputType == BabelData::fileType);
-    fidx = formatIndexFromName(outIsFile, (outIsFile ?
-                                          bd.outputFileFormat : bd.outputDeviceFormat));
-    args << "-o";
-    args << (formatList[fidx].getName() + MakeOptions(formatList[fidx].getOutputOptions()));
-
-    // output file or device option
-    if (outIsFile) {
-      if (bd.outputFileName != "")
-             args << "-F" << bd.outputFileName;
-    }
-    else if (bd.outputType == BabelData::deviceType) {
-      args << "-F" << bd.outputDeviceName;
-    }
-    // GUI only ever writes a single file at a time.
-    formatList[fidx].bumpWriteUseCount(1);
-  }
-
-  // Now output for preview in google maps
-  QString tempName;
-  if (bd.previewGmap) {
-    QTemporaryFile ftemp;
-    ftemp.open();
-    tempName = ftemp.fileName();
-    ftemp.close();
-
-    // Ideally, expost this in the UI.  For now, just split the track
-    // if we've no recorded fixes for > 5 mins and we've moved > 300 meters.
-    //args << "-x";
-    //args << "track,pack,sdistance=0.3k,split=5m";
-
-    args << "-o";
-    args << "gpx";
-    args << "-F" << tempName;
-  }
-
-  ui.outputWindow->clear();
-  ui.outputWindow->appendPlainText("gpsbabel " + args.join(" "));
-
-  QString errorString, outputString;
-  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-  bool x = runGpsbabel(args, errorString, outputString);
-  QApplication::restoreOverrideCursor();
-
-  ui.outputWindow->appendPlainText(outputString);
-  if (x) {
-    ui.outputWindow->appendPlainText(tr("Translation successful"));
-    if (bd.previewGmap) {
-      this->hide();
-      GMapDialog dlg(0, tempName, bd.debugLevel >=1 ? ui.outputWindow : 0);
-      dlg.show();
-      dlg.exec();
-      this->show();
-    }
-  }
-  else
-    ui.outputWindow->appendPlainText(tr("Error running gpsbabel: %1\n").arg(errorString));
-}
-
-//------------------------------------------------------------------------
-void MainWindow::closeActionX()
-{
-  QDateTime wt= upgrade->getUpgradeWarningTime();
-  if (wt.isValid()) {
-    bd.upgradeCheckTime = wt;
-  }
-  bd.runCount++;
-
-  QDateTime now = QDateTime::currentDateTime();
-  if ((bd.runCount > 5) && (bd.donateSplashed.daysTo(now) > 30)) {
-    Donate donate(0);
-    if (bd.donateSplashed.date() == QDate(2010,1,1))
-      donate.showNever(false);
-    donate.exec();
-    bd.donateSplashed = now;
-  }
-  saveSettings();
-  delete upgrade;
-  upgrade = 0;
-  qApp->exit(0);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::closeEvent(QCloseEvent*)
-{
-  closeActionX();
-}
-
-//------------------------------------------------------------------------
-void MainWindow::donateActionX()
-{
-  QDesktopServices::openUrl(QString("http://www.gpsbabel.org/contribute.html?gbversion=" VERSION));
-}
-
-//------------------------------------------------------------------------
-void MainWindow::visitWebsiteActionX()
-{
-  QDesktopServices::openUrl(QString("http://www.gpsbabel.org"));
-}
-
-//------------------------------------------------------------------------
-void MainWindow::dragEnterEvent(QDragEnterEvent *event)
-{
-  event->acceptProposedAction();
-}
-
-void MainWindow::dropEvent(QDropEvent *event)
-{
-  foreach (QString format, event->mimeData()->formats()) {
-    if (format == "text/uri-list") {
-      QList<QUrl> urlList = event->mimeData()->urls();
-      bd.inputFileNames.clear();
-      for (int i = 0; i < urlList.size(); ++i) {
-        QFileInfo file_info(urlList.at(i).path());
-        QString name = file_info.filePath();
-        QString ext = file_info.suffix();
-
-        QString fmt = getFormatNameForExtension(ext);
-        setComboToFormat(ui.inputFormatCombo, fmt, true);
-        ui.inputFileNameText->setText(name);
-        bd.inputFileNames << ui.inputFileNameText->text();
-        event->acceptProposedAction();
-      }
-    }
-  }
-}
-//------------------------------------------------------------------------
-void MainWindow::setComboToDevice(QComboBox *comboBox, const QString &name)
-{
-  for (int i=0; i<comboBox->count(); i++) {
-    if (comboBox->itemText(i) == name) {
-      comboBox->setCurrentIndex(i);
-      break;
-    }
-  }
-}
-
-//------------------------------------------------------------------------
-void MainWindow::saveSettings()
-{
-  getWidgetValues();
-
-  QSettings settings;
-  bd.saveSettings(settings);
-  for (int i=0; i<formatList.size(); i++)
-    formatList[i].saveSettings(settings);
-  for (int i=0; i<filterData.filters.size(); i++)
-    filterData.filters[i]->saveSettings(settings);
-}
-
-//------------------------------------------------------------------------
-void MainWindow::restoreSettings()
-{
-  QSettings settings;
-  bd.restoreSettings(settings);
-  for (int i=0; i<formatList.size(); i++)
-    formatList[i].restoreSettings(settings);
-
-  for (int i=0; i<filterData.filters.size(); i++)
-    filterData.filters[i]->restoreSettings(settings);
-
-  setWidgetValues();
-}
-
-//------------------------------------------------------------------------
-void MainWindow::resetFormatDefaults()
-{
-  int ret = QMessageBox::warning
-    (this, QString(appName),
-     tr("Are you sure you want to reset all format options to default values?"),
-     QMessageBox::Yes | QMessageBox::No);
-  if (ret == QMessageBox::Yes) {
-    for (int i=0; i<formatList.size(); i++)
-      formatList[i].setToDefault();
-    displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
-    displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
-  }
-}
-
-//------------------------------------------------------------------------
-void MainWindow::moreOptionButtonClicked()
-{
-  AdvDlg advDlg(0, bd.synthShortNames,
-               bd.enableCharSetXform, bd.previewGmap, bd.debugLevel);
-  connect(advDlg.formatButton(), SIGNAL(clicked()),
-         this, SLOT(resetFormatDefaults()));
-  advDlg.exec();
-  checkCharSetCombos();
-}
-//------------------------------------------------------------------------
-void MainWindow::aboutActionX()
-{
-  AboutDlg aboutDlg(0, babelVersion, QString(appName) + QString(" " VERSION));
-  aboutDlg.setWindowTitle(tr("About %1").arg(appName));
-  aboutDlg.exec();
-}
-
-//------------------------------------------------------------------------
-void MainWindow::upgradeCheckActionX()
-{
-    upgrade->checkForUpgrade(babelVersion, 
-                            QDateTime(QDate(2000, 1, 1), QTime(0, 0)), 
-                            allowBetaUpgrades());
-}
-
-//------------------------------------------------------------------------
-void MainWindow::preferencesActionX()
-{
-  Preferences preferences(0, formatList, bd);
-  preferences.exec();
-
-  // We may have changed the list of displayed formats.  Resynchronize.
-  setWidgetValues();
-}
-
-
-//------------------------------------------------------------------------
-void MainWindow::helpActionX()
-{
-  ShowHelp("index.html");
-}
-//------------------------------------------------------------------------
-void MainWindow::filtersClicked()
-{
-  FilterDialog dlg(0, filterData);
-  dlg.runDialog();
-  updateFilterStatus();
-}
-
-
-//------------------------------------------------------------------------
-void MainWindow::updateFilterStatus()
-{
-  bool filterActive = filterData.getAllFilterStrings().size();
-  ui.filterStatus->setEnabled(filterActive);
-  if (filterActive)
-    ui.filterStatus->setToolTip(tr("One or more data filters are active"));
-  else {
-    ui.filterStatus->setToolTip(tr("No data filters are active"));
-  }
-}
-//------------------------------------------------------------------------
-void MainWindow::setWidgetValues()
-{
-  if (bd.inputType == BabelData::fileType) {
-    ui.inputFileOptBtn->setChecked(true);
-    inputFileOptBtnClicked();
-    setComboToFormat(ui.inputFormatCombo, bd.inputFileFormat, true);
-    ui.inputStackedWidget->setCurrentWidget(ui.inputFilePage);
-  }
-  else {
-    ui.inputDeviceOptBtn->setChecked(true);
-    inputDeviceOptBtnClicked();
-    setComboToFormat(ui.inputFormatCombo, bd.inputDeviceFormat, false);
-    loadInputDeviceNameCombo(bd.inputDeviceFormat);
-    ui.inputStackedWidget->setCurrentWidget(ui.inputDevicePage);
-  }
-  setComboToDevice(ui.inputDeviceNameCombo, bd.inputDeviceName);
-  setComboToCharSet(ui.inputCharSetCombo, bd.inputCharSet);
-
-  if (bd.outputType == BabelData::fileType) {
-    ui.outputFileOptBtn->setChecked(true);
-    outputFileOptBtnClicked();
-    setComboToFormat(ui.outputFormatCombo, bd.outputFileFormat, true);
-    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
-  }
-  else if (bd.outputType == BabelData::deviceType) {
-    ui.outputDeviceOptBtn->setChecked(true);
-    outputDeviceOptBtnClicked();
-    setComboToFormat(ui.outputFormatCombo, bd.outputDeviceFormat, false);
-    loadOutputDeviceNameCombo(bd.outputDeviceFormat);
-    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
-  }
-  else {
-    ui.outputFileOptBtn->setChecked(false);
-    ui.outputDeviceOptBtn->setChecked(false);
-    setComboToFormat(ui.outputFormatCombo, bd.outputFileFormat, true);
-    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
-    ui.outputFilePage->setDisabled(true);
-  }
-
-  setComboToDevice(ui.outputDeviceNameCombo, bd.outputDeviceName);
-  setComboToCharSet(ui.outputCharSetCombo, bd.outputCharSet);
-
-  ui.xlateWayPtsCk->setChecked(bd.xlateWayPts);
-  ui.xlateTracksCk->setChecked(bd.xlateTracks);
-  ui.xlateRoutesCk->setChecked(bd.xlateRoutes);
-
-  crossCheckInOutFormats();
-  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
-  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
-  checkCharSetCombos();
-  updateFilterStatus();
-}
-
-//------------------------------------------------------------------------
-void MainWindow::getWidgetValues()
-{
-  int comboIdx = ui.inputFormatCombo->currentIndex();
-  int fidx = ui.inputFormatCombo->itemData(comboIdx).toInt();
-  if (ui.inputFileOptBtn->isChecked()){
-    bd.inputType = BabelData::fileType;
-    bd.inputFileFormat =formatList[fidx].getName();
-  }
-  else {
-    bd.inputType = BabelData::deviceType;
-    bd.inputDeviceFormat =formatList[fidx].getName();
-  }
-  bd.inputDeviceName = ui.inputDeviceNameCombo->currentText();
-  bd.inputCharSet = charSetFromCombo(ui.inputCharSetCombo);
-
-  comboIdx = ui.outputFormatCombo->currentIndex();
-  fidx = ui.outputFormatCombo->itemData(comboIdx).toInt();
-  if (ui.outputFileOptBtn->isChecked()){
-    bd.outputType = BabelData::fileType;
-    bd.outputFileFormat =formatList[fidx].getName();
-  }
-  else if (ui.outputDeviceOptBtn->isChecked()){
-    bd.outputType = BabelData::deviceType;
-    bd.outputDeviceFormat =formatList[fidx].getName();
-  }
-  else {
-    bd.outputType = BabelData::noType;
-  }
-  bd.outputDeviceName = ui.outputDeviceNameCombo->currentText();
-  bd.outputCharSet = charSetFromCombo(ui.outputCharSetCombo);
-
-  bd.xlateWayPts = ui.xlateWayPtsCk->isChecked();
-  bd.xlateTracks = ui.xlateTracksCk->isChecked();
-  bd.xlateRoutes = ui.xlateRoutesCk->isChecked();
-}
-
-// This could be made faster, but any attempt to do so would have to be
-// careful about disabled formats.  As it was written to be handled by a
-// drag response, performance is hardly critical.
-// It's also kind of dumb to return the name which SetCombo then looks up,
-// but there's not a 1:1 correlation between offsets in the combo box and
-// in the list of formats.
-QString MainWindow::getFormatNameForExtension(QString ext)
-{
-  for (int i = 0; i < formatList.size(); i++) {
-    QStringList extensions = formatList[i].getExtensions();
-    for (int j = 0; j < extensions.size(); ++j) {
-      if (extensions[j] == ext) {
-        return formatList[i].getName();;
-      }
-    }
-  }
-  return 0;
-}
diff --git a/gpsbabel/gui/map.cc b/gpsbabel/gui/map.cc
new file mode 100644 (file)
index 0000000..21e4c23
--- /dev/null
@@ -0,0 +1,442 @@
+// -*- C++ -*-
+// $Id: map.cpp,v 1.2 2009-08-28 17:08:55 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#include <QNetworkRequest>
+#include <QMessageBox>
+#include <QNetworkAccessManager>
+#include <QWebFrame>
+#include <QWebPage>
+#include <QApplication>
+#include <QCursor>
+#include <QFile>
+
+#include <math.h>
+#include "map.h"
+#include "appname.h"
+#include "dpencode.h"
+
+//------------------------------------------------------------------------
+static QString stripDoubleQuotes(const QString s) {
+  QString out;
+  foreach (QChar c, s) {
+    if (c != QChar('"'))
+      out += c;
+  }
+  return out;
+}
+
+//------------------------------------------------------------------------
+Map::Map(QWidget *parent,
+        const Gpx  &gpx, QPlainTextEdit *te):
+    QWebView(parent),
+    gpx(gpx),
+    mapPresent(false),
+    busyCursor(false),
+    te(te)
+{
+  busyCursor = true;
+  stopWatch.start();
+  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  manager = new QNetworkAccessManager(this);
+  connect(this,SIGNAL(loadFinished(bool)),
+         this,SLOT(loadFinishedX(bool)));
+  this->logTimeX("Start map constuctor");
+  QString baseFile =  QApplication::applicationDirPath() + "/gmapbase.html";
+  if (!QFile(baseFile).exists()) {
+    QMessageBox::critical(0, appName,
+                         tr("Missing \"gmapbase.html\" file.  Check installation"));
+  }
+  else {
+    QString urlStr = "file:///" + baseFile;
+    load(QUrl(urlStr));
+  }
+}
+
+//------------------------------------------------------------------------
+Map::~Map()
+{
+  if (busyCursor)
+    QApplication::restoreOverrideCursor();
+}
+//------------------------------------------------------------------------
+void Map::loadFinishedX(bool f)
+{
+  this->logTimeX("Done initial page load");
+  if (!f)
+    QMessageBox::critical(0, appName,
+                         tr("Failed to load Google maps base page"));
+  else {
+    QApplication::processEvents();
+    showGpxData();
+  }
+  QApplication::restoreOverrideCursor();
+  busyCursor = false;
+}
+
+//------------------------------------------------------------------------
+
+static QStringList makeLiteralVar(const QString &name, const string &s)
+{
+  QStringList out;
+  out << QString("var %1 = ").arg(name);
+
+  QString ws = "\"";
+  for (unsigned int i=0; i<s.length(); i++) {
+    if (s[i] =='\\') {
+      ws += s[i];
+    }
+    ws += s[i];
+    if (ws.length() > 5120) {
+      ws += "\" + ";
+      out << ws;
+      ws = "\"";
+    }
+  }
+  ws += "\";";
+  out << ws;
+  return out;
+}
+
+//------------------------------------------------------------------------
+static QString fmtLatLng(const LatLng &l) {
+  return  QString("%1, %3").arg(l.lat(), 0, 'f', 5) .arg(l.lng(), 0, 'f', 5);
+}
+
+//------------------------------------------------------------------------
+void Map::showGpxData()
+{
+  MarkerClicker *mclicker = new MarkerClicker(this);
+  this->page()->mainFrame()->addToJavaScriptWindowObject("mclicker", mclicker);
+  connect(mclicker, SIGNAL(markerClicked(int, int )), this, SLOT(markerClicked(int, int)));
+  connect(mclicker, SIGNAL(logTime(const QString &)), this, SLOT(logTimeX(const QString &)));
+
+  // It is appreciably faster to do the encoding on the C++ side.
+  int numLevels = 18;
+  double zoomFactor = 2;
+  PolylineEncoder encoder(numLevels, zoomFactor, 0.00001);
+
+
+  this->logTimeX("Start defining JS string");
+  QStringList scriptStr;
+  scriptStr
+    << "mclicker.logTime(\"Start JS execution\");"
+    << "var map = new GMap2(document.getElementById(\"map\"));"
+    << "var bounds = new GLatLngBounds;"
+    << "var waypts = [];"
+    << "var rtes = [];"
+    << "var trks = [];"
+    << "map.enableScrollWheelZoom();"
+    << "map.enableContinuousZoom();"
+    << "map.addControl(new GLargeMapControl());"
+    << "map.addControl(new GScaleControl());"
+    << "map.addControl(new GMapTypeControl());"
+    << "var pn = map.getPane(G_MAP_MARKER_PANE);"
+    << "pn.style.KhtmlUserSelect='none';"
+    << "pn.style.KhtmlUserDrag='none';"
+    << "mclicker.logTime(\"Done prelim JS definition\");"
+    << QString("var zoomFactor = %1;").arg(zoomFactor)
+    << QString("var numLevels = %1;").arg(numLevels)
+    ;
+
+  mapPresent = true;
+
+  // Waypoints.
+  int num=0;
+  foreach (const  GpxWaypoint &pt, gpx.getWaypoints() ) {
+    scriptStr
+      << QString("waypts[%1] = new GMarker(new GLatLng(%2), "
+                "{title:\"%3\",icon:blueIcon});")
+      .arg(num)
+      .arg(fmtLatLng(pt.getLocation()))
+      .arg(stripDoubleQuotes(pt.getName()));
+    num++;
+  }
+
+  scriptStr
+    << "for( var i=0; i<waypts.length; ++i ) {"
+    << "   bounds.extend(waypts[i].getPoint());"
+    << "   var ftemp = new MarkerHandler(0, i);"
+    << "   GEvent.bind(waypts[i], \"click\", ftemp, ftemp.clicked);"
+    << "   map.addOverlay(waypts[i]);"
+    << "}"
+    << "mclicker.logTime(\"Done waypoints definition\");"
+    ;
+
+  // Tracks
+  num = 0;
+  foreach (const GpxTrack &trk, gpx.getTracks()) {
+    vector <LatLng> epts;
+    foreach (const GpxTrackSegment seg, trk.getTrackSegments()) {
+      foreach (const GpxTrackPoint pt, seg.getTrackPoints()) {
+       epts.push_back(pt.getLocation());
+      }
+    }
+    string encPts, encLevels;
+    encoder.dpEncode(encPts, encLevels, epts);
+
+    scriptStr
+      << QString("var startPt = new GLatLng(%1);").arg(fmtLatLng(epts[0]))
+      << QString("var endPt = new GLatLng(%1);").arg(fmtLatLng(epts[epts.size()-1]))
+      << QString("var idx = %1;").arg(num)
+      << QString("var nm = \"%1\";").arg(stripDoubleQuotes(trk.getName()))
+      << makeLiteralVar("encpts", encPts)
+      << makeLiteralVar("enclvs", encLevels)
+
+      << "var trk   = GPolyline.fromEncoded({color:\"#0000E0\", weight:2, opacity:0.6,"
+      <<                   "points:encpts, zoomFactor:zoomFactor, levels:enclvs, numLevels:numLevels});"
+      << "trks[idx] =  new RTPolyline(trk, startPt, endPt, new MarkerHandler(1, idx));"
+      ;
+    num++;
+  }
+
+  scriptStr
+    << "for( var i=0; i<trks.length; ++i ) {"
+    << "   var trkbound = trks[i].getBounds();"
+    << "   bounds.extend(trkbound.getSouthWest());"
+    << "   bounds.extend(trkbound.getNorthEast());"
+    << "}"
+    << "mclicker.logTime(\"Done track definition\");"
+    ;
+
+  // Routes
+  num = 0;
+  foreach (const GpxRoute &rte, gpx.getRoutes()) {
+    vector <LatLng> epts;
+    foreach (const GpxRoutePoint &pt, rte.getRoutePoints()) {
+      epts.push_back(pt.getLocation());
+    }
+    string encPts, encLevels;
+    encoder.dpEncode(encPts, encLevels, epts);
+    scriptStr
+      << QString("var startPt = new GLatLng(%1);").arg(fmtLatLng(epts[0]))
+      << QString("var endPt = new GLatLng(%1);").arg(fmtLatLng(epts[epts.size()-1]))
+      << QString("var idx = %1;").arg(num)
+      << QString("var nm = \"%1\";").arg(stripDoubleQuotes(rte.getName()))
+      << makeLiteralVar("encpts", encPts)
+      << makeLiteralVar("enclvs", encLevels)
+      << "var rte = GPolyline.fromEncoded({color:\"#8000B0\", weight:2, opacity:0.6,"
+      << "                       points:encpts, zoomFactor:zoomFactor, levels:enclvs, numLevels:numLevels});"
+      << "rtes[idx] = new RTPolyline(rte, startPt, endPt, new MarkerHandler(2, idx));"
+      ;
+    num++;
+  }
+
+  scriptStr
+    << "for( var i=0; i<rtes.length; ++i ) {"
+    << "   var rtebound = rtes[i].getBounds();"
+    << "   bounds.extend(rtebound.getSouthWest());"
+    << "   bounds.extend(rtebound.getNorthEast());"
+    << "}"
+    << "mclicker.logTime(\"Done route definition\");"
+    ;
+
+  scriptStr
+    << "map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));"
+    << "mclicker.logTime(\"done setCenter\");"
+    ;
+
+  this->logTimeX("Done defining JS string");
+  evaluateJS(scriptStr);
+  this->logTimeX("Done JS evaluation");
+}
+
+//------------------------------------------------------------------------
+void Map::markerClicked(int t, int i){
+  if (t == 0)
+    emit waypointClicked(i);
+  else if (t == 1)
+    emit trackClicked(i);
+  else if (t == 2)
+    emit routeClicked(i);
+
+}
+
+//------------------------------------------------------------------------
+void Map::logTimeX(const QString &s)
+{
+  //  fprintf(stderr, "Log: %s:  %d ms\n", s.toStdString().c_str(), stopWatch.elapsed());
+  if (te) {
+    te->appendPlainText(QString("%1: %2 ms").arg(s).arg(stopWatch.elapsed()));
+  }
+  stopWatch.start();
+}
+//------------------------------------------------------------------------
+void Map::showTracks(const QList<GpxTrack> &tracks)
+{
+  QStringList scriptStr;
+  int i=0;
+  foreach(const GpxTrack &trk, tracks) {
+    scriptStr << QString("trks[%1].%2();").arg(i).arg(trk.getVisible()?"show":"hide");
+    i++;
+  }
+  evaluateJS(scriptStr);
+}
+
+//------------------------------------------------------------------------
+void Map::hideAllTracks()
+{
+  QStringList scriptStr;
+  scriptStr
+    << "for( var i=0; i<trks.length; ++i ) {"
+    << "   trks[i].hide();"
+    << "}"
+    ;
+  evaluateJS(scriptStr);
+}
+
+//------------------------------------------------------------------------
+void Map::showWaypoints(const QList<GpxWaypoint> &waypoints)
+{
+  QStringList scriptStr;
+  int i=0;
+  foreach(const GpxWaypoint &pt, waypoints) {
+    scriptStr << QString("waypts[%1].%2();").arg(i++).arg(pt.getVisible()?"show":"hide");
+  }
+  evaluateJS(scriptStr);
+}
+//------------------------------------------------------------------------
+void Map::hideAllWaypoints()
+{
+  QStringList scriptStr;
+  scriptStr
+    << "for( var i=0; i<waypts.length; ++i ) {"
+    << "   waypts[i].hide();"
+    << "}"
+    ;
+  evaluateJS(scriptStr);
+}
+
+//------------------------------------------------------------------------
+void Map::showRoutes(const QList<GpxRoute> &routes)
+{
+  QStringList scriptStr;
+  int i=0;
+  foreach(const GpxRoute &rt, routes) {
+    scriptStr << QString("rtes[%1].%2();").arg(i).arg(rt.getVisible()?"show":"hide");
+    i++;
+  }
+  evaluateJS(scriptStr);
+}
+//------------------------------------------------------------------------
+void Map::hideAllRoutes()
+{
+  QStringList scriptStr;
+  scriptStr
+    << "for( var i=0; i<rtes.length; ++i ) {"
+    << "   rtes[i].hide();"
+    << "}"
+    ;
+  evaluateJS(scriptStr);
+}
+//------------------------------------------------------------------------
+void Map::setWaypointVisibility(int i, bool show)
+{
+  evaluateJS(QString("waypts[%1].%2();\n")
+            .arg(i).arg(show?"show": "hide"));
+}
+
+//------------------------------------------------------------------------
+void Map::setTrackVisibility(int i, bool show)
+{
+  QString x = show?"show": "hide";
+  QStringList scriptStr;
+  scriptStr
+    << QString("trks[%1].%2();").arg(i).arg(x)
+    ;
+  evaluateJS(scriptStr);
+}
+
+//------------------------------------------------------------------------
+void Map::setRouteVisibility(int i, bool show)
+{
+  QString x = show?"show": "hide";
+  QStringList scriptStr;
+  scriptStr
+    << QString("rtes[%1].%2();").arg(i).arg(x)
+    ;
+  evaluateJS(scriptStr);
+}
+
+//------------------------------------------------------------------------
+void Map::panTo(const LatLng &loc)
+{
+  evaluateJS(QString("map.panTo(new GLatLng(%1));").arg(fmtLatLng(loc)));
+}
+
+//------------------------------------------------------------------------
+void Map::resizeEvent ( QResizeEvent * ev)
+{
+  QWebView::resizeEvent(ev);
+  if (mapPresent)
+    evaluateJS(QString("map.checkResize();"));
+}
+
+//------------------------------------------------------------------------
+void Map::setWaypointColorRed(int i)
+{
+  evaluateJS(QString("waypts[%1].setImage(redIcon.image)").arg(i));
+}
+
+//------------------------------------------------------------------------
+void Map::setWaypointColorBlue(int i)
+{
+  evaluateJS(QString("waypts[%1].setImage(blueIcon.image)").arg(i));
+}
+
+//------------------------------------------------------------------------
+void Map::frameTrack(int i)
+{
+  QStringList scriptStr;
+  scriptStr
+    << QString("var trkbound = trks[%1].getBounds();").arg(i)
+    << "map.setCenter(trkbound.getCenter(), map.getBoundsZoomLevel(trkbound));"
+    ;
+  evaluateJS(scriptStr);
+}
+
+
+//------------------------------------------------------------------------
+void Map::frameRoute(int i)
+{
+  QStringList scriptStr;
+  scriptStr
+    << QString("var rtebound = rtes[%1].getBounds();").arg(i)
+    << "map.setCenter(rtebound.getCenter(), map.getBoundsZoomLevel(rtebound));"
+    ;
+  evaluateJS(scriptStr);
+}
+
+
+//------------------------------------------------------------------------
+void Map::evaluateJS(const QString &s, bool upd)
+{
+  this->page()->mainFrame()->evaluateJavaScript(s);
+  if (upd) {
+    this->update();
+  }
+}
+
+//------------------------------------------------------------------------
+void Map::evaluateJS(const QStringList &s, bool upd)
+{
+  evaluateJS(s.join("\n"), upd);
+}
diff --git a/gpsbabel/gui/map.cpp b/gpsbabel/gui/map.cpp
deleted file mode 100644 (file)
index 21e4c23..0000000
+++ /dev/null
@@ -1,442 +0,0 @@
-// -*- C++ -*-
-// $Id: map.cpp,v 1.2 2009-08-28 17:08:55 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#include <QNetworkRequest>
-#include <QMessageBox>
-#include <QNetworkAccessManager>
-#include <QWebFrame>
-#include <QWebPage>
-#include <QApplication>
-#include <QCursor>
-#include <QFile>
-
-#include <math.h>
-#include "map.h"
-#include "appname.h"
-#include "dpencode.h"
-
-//------------------------------------------------------------------------
-static QString stripDoubleQuotes(const QString s) {
-  QString out;
-  foreach (QChar c, s) {
-    if (c != QChar('"'))
-      out += c;
-  }
-  return out;
-}
-
-//------------------------------------------------------------------------
-Map::Map(QWidget *parent,
-        const Gpx  &gpx, QPlainTextEdit *te):
-    QWebView(parent),
-    gpx(gpx),
-    mapPresent(false),
-    busyCursor(false),
-    te(te)
-{
-  busyCursor = true;
-  stopWatch.start();
-  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-  manager = new QNetworkAccessManager(this);
-  connect(this,SIGNAL(loadFinished(bool)),
-         this,SLOT(loadFinishedX(bool)));
-  this->logTimeX("Start map constuctor");
-  QString baseFile =  QApplication::applicationDirPath() + "/gmapbase.html";
-  if (!QFile(baseFile).exists()) {
-    QMessageBox::critical(0, appName,
-                         tr("Missing \"gmapbase.html\" file.  Check installation"));
-  }
-  else {
-    QString urlStr = "file:///" + baseFile;
-    load(QUrl(urlStr));
-  }
-}
-
-//------------------------------------------------------------------------
-Map::~Map()
-{
-  if (busyCursor)
-    QApplication::restoreOverrideCursor();
-}
-//------------------------------------------------------------------------
-void Map::loadFinishedX(bool f)
-{
-  this->logTimeX("Done initial page load");
-  if (!f)
-    QMessageBox::critical(0, appName,
-                         tr("Failed to load Google maps base page"));
-  else {
-    QApplication::processEvents();
-    showGpxData();
-  }
-  QApplication::restoreOverrideCursor();
-  busyCursor = false;
-}
-
-//------------------------------------------------------------------------
-
-static QStringList makeLiteralVar(const QString &name, const string &s)
-{
-  QStringList out;
-  out << QString("var %1 = ").arg(name);
-
-  QString ws = "\"";
-  for (unsigned int i=0; i<s.length(); i++) {
-    if (s[i] =='\\') {
-      ws += s[i];
-    }
-    ws += s[i];
-    if (ws.length() > 5120) {
-      ws += "\" + ";
-      out << ws;
-      ws = "\"";
-    }
-  }
-  ws += "\";";
-  out << ws;
-  return out;
-}
-
-//------------------------------------------------------------------------
-static QString fmtLatLng(const LatLng &l) {
-  return  QString("%1, %3").arg(l.lat(), 0, 'f', 5) .arg(l.lng(), 0, 'f', 5);
-}
-
-//------------------------------------------------------------------------
-void Map::showGpxData()
-{
-  MarkerClicker *mclicker = new MarkerClicker(this);
-  this->page()->mainFrame()->addToJavaScriptWindowObject("mclicker", mclicker);
-  connect(mclicker, SIGNAL(markerClicked(int, int )), this, SLOT(markerClicked(int, int)));
-  connect(mclicker, SIGNAL(logTime(const QString &)), this, SLOT(logTimeX(const QString &)));
-
-  // It is appreciably faster to do the encoding on the C++ side.
-  int numLevels = 18;
-  double zoomFactor = 2;
-  PolylineEncoder encoder(numLevels, zoomFactor, 0.00001);
-
-
-  this->logTimeX("Start defining JS string");
-  QStringList scriptStr;
-  scriptStr
-    << "mclicker.logTime(\"Start JS execution\");"
-    << "var map = new GMap2(document.getElementById(\"map\"));"
-    << "var bounds = new GLatLngBounds;"
-    << "var waypts = [];"
-    << "var rtes = [];"
-    << "var trks = [];"
-    << "map.enableScrollWheelZoom();"
-    << "map.enableContinuousZoom();"
-    << "map.addControl(new GLargeMapControl());"
-    << "map.addControl(new GScaleControl());"
-    << "map.addControl(new GMapTypeControl());"
-    << "var pn = map.getPane(G_MAP_MARKER_PANE);"
-    << "pn.style.KhtmlUserSelect='none';"
-    << "pn.style.KhtmlUserDrag='none';"
-    << "mclicker.logTime(\"Done prelim JS definition\");"
-    << QString("var zoomFactor = %1;").arg(zoomFactor)
-    << QString("var numLevels = %1;").arg(numLevels)
-    ;
-
-  mapPresent = true;
-
-  // Waypoints.
-  int num=0;
-  foreach (const  GpxWaypoint &pt, gpx.getWaypoints() ) {
-    scriptStr
-      << QString("waypts[%1] = new GMarker(new GLatLng(%2), "
-                "{title:\"%3\",icon:blueIcon});")
-      .arg(num)
-      .arg(fmtLatLng(pt.getLocation()))
-      .arg(stripDoubleQuotes(pt.getName()));
-    num++;
-  }
-
-  scriptStr
-    << "for( var i=0; i<waypts.length; ++i ) {"
-    << "   bounds.extend(waypts[i].getPoint());"
-    << "   var ftemp = new MarkerHandler(0, i);"
-    << "   GEvent.bind(waypts[i], \"click\", ftemp, ftemp.clicked);"
-    << "   map.addOverlay(waypts[i]);"
-    << "}"
-    << "mclicker.logTime(\"Done waypoints definition\");"
-    ;
-
-  // Tracks
-  num = 0;
-  foreach (const GpxTrack &trk, gpx.getTracks()) {
-    vector <LatLng> epts;
-    foreach (const GpxTrackSegment seg, trk.getTrackSegments()) {
-      foreach (const GpxTrackPoint pt, seg.getTrackPoints()) {
-       epts.push_back(pt.getLocation());
-      }
-    }
-    string encPts, encLevels;
-    encoder.dpEncode(encPts, encLevels, epts);
-
-    scriptStr
-      << QString("var startPt = new GLatLng(%1);").arg(fmtLatLng(epts[0]))
-      << QString("var endPt = new GLatLng(%1);").arg(fmtLatLng(epts[epts.size()-1]))
-      << QString("var idx = %1;").arg(num)
-      << QString("var nm = \"%1\";").arg(stripDoubleQuotes(trk.getName()))
-      << makeLiteralVar("encpts", encPts)
-      << makeLiteralVar("enclvs", encLevels)
-
-      << "var trk   = GPolyline.fromEncoded({color:\"#0000E0\", weight:2, opacity:0.6,"
-      <<                   "points:encpts, zoomFactor:zoomFactor, levels:enclvs, numLevels:numLevels});"
-      << "trks[idx] =  new RTPolyline(trk, startPt, endPt, new MarkerHandler(1, idx));"
-      ;
-    num++;
-  }
-
-  scriptStr
-    << "for( var i=0; i<trks.length; ++i ) {"
-    << "   var trkbound = trks[i].getBounds();"
-    << "   bounds.extend(trkbound.getSouthWest());"
-    << "   bounds.extend(trkbound.getNorthEast());"
-    << "}"
-    << "mclicker.logTime(\"Done track definition\");"
-    ;
-
-  // Routes
-  num = 0;
-  foreach (const GpxRoute &rte, gpx.getRoutes()) {
-    vector <LatLng> epts;
-    foreach (const GpxRoutePoint &pt, rte.getRoutePoints()) {
-      epts.push_back(pt.getLocation());
-    }
-    string encPts, encLevels;
-    encoder.dpEncode(encPts, encLevels, epts);
-    scriptStr
-      << QString("var startPt = new GLatLng(%1);").arg(fmtLatLng(epts[0]))
-      << QString("var endPt = new GLatLng(%1);").arg(fmtLatLng(epts[epts.size()-1]))
-      << QString("var idx = %1;").arg(num)
-      << QString("var nm = \"%1\";").arg(stripDoubleQuotes(rte.getName()))
-      << makeLiteralVar("encpts", encPts)
-      << makeLiteralVar("enclvs", encLevels)
-      << "var rte = GPolyline.fromEncoded({color:\"#8000B0\", weight:2, opacity:0.6,"
-      << "                       points:encpts, zoomFactor:zoomFactor, levels:enclvs, numLevels:numLevels});"
-      << "rtes[idx] = new RTPolyline(rte, startPt, endPt, new MarkerHandler(2, idx));"
-      ;
-    num++;
-  }
-
-  scriptStr
-    << "for( var i=0; i<rtes.length; ++i ) {"
-    << "   var rtebound = rtes[i].getBounds();"
-    << "   bounds.extend(rtebound.getSouthWest());"
-    << "   bounds.extend(rtebound.getNorthEast());"
-    << "}"
-    << "mclicker.logTime(\"Done route definition\");"
-    ;
-
-  scriptStr
-    << "map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));"
-    << "mclicker.logTime(\"done setCenter\");"
-    ;
-
-  this->logTimeX("Done defining JS string");
-  evaluateJS(scriptStr);
-  this->logTimeX("Done JS evaluation");
-}
-
-//------------------------------------------------------------------------
-void Map::markerClicked(int t, int i){
-  if (t == 0)
-    emit waypointClicked(i);
-  else if (t == 1)
-    emit trackClicked(i);
-  else if (t == 2)
-    emit routeClicked(i);
-
-}
-
-//------------------------------------------------------------------------
-void Map::logTimeX(const QString &s)
-{
-  //  fprintf(stderr, "Log: %s:  %d ms\n", s.toStdString().c_str(), stopWatch.elapsed());
-  if (te) {
-    te->appendPlainText(QString("%1: %2 ms").arg(s).arg(stopWatch.elapsed()));
-  }
-  stopWatch.start();
-}
-//------------------------------------------------------------------------
-void Map::showTracks(const QList<GpxTrack> &tracks)
-{
-  QStringList scriptStr;
-  int i=0;
-  foreach(const GpxTrack &trk, tracks) {
-    scriptStr << QString("trks[%1].%2();").arg(i).arg(trk.getVisible()?"show":"hide");
-    i++;
-  }
-  evaluateJS(scriptStr);
-}
-
-//------------------------------------------------------------------------
-void Map::hideAllTracks()
-{
-  QStringList scriptStr;
-  scriptStr
-    << "for( var i=0; i<trks.length; ++i ) {"
-    << "   trks[i].hide();"
-    << "}"
-    ;
-  evaluateJS(scriptStr);
-}
-
-//------------------------------------------------------------------------
-void Map::showWaypoints(const QList<GpxWaypoint> &waypoints)
-{
-  QStringList scriptStr;
-  int i=0;
-  foreach(const GpxWaypoint &pt, waypoints) {
-    scriptStr << QString("waypts[%1].%2();").arg(i++).arg(pt.getVisible()?"show":"hide");
-  }
-  evaluateJS(scriptStr);
-}
-//------------------------------------------------------------------------
-void Map::hideAllWaypoints()
-{
-  QStringList scriptStr;
-  scriptStr
-    << "for( var i=0; i<waypts.length; ++i ) {"
-    << "   waypts[i].hide();"
-    << "}"
-    ;
-  evaluateJS(scriptStr);
-}
-
-//------------------------------------------------------------------------
-void Map::showRoutes(const QList<GpxRoute> &routes)
-{
-  QStringList scriptStr;
-  int i=0;
-  foreach(const GpxRoute &rt, routes) {
-    scriptStr << QString("rtes[%1].%2();").arg(i).arg(rt.getVisible()?"show":"hide");
-    i++;
-  }
-  evaluateJS(scriptStr);
-}
-//------------------------------------------------------------------------
-void Map::hideAllRoutes()
-{
-  QStringList scriptStr;
-  scriptStr
-    << "for( var i=0; i<rtes.length; ++i ) {"
-    << "   rtes[i].hide();"
-    << "}"
-    ;
-  evaluateJS(scriptStr);
-}
-//------------------------------------------------------------------------
-void Map::setWaypointVisibility(int i, bool show)
-{
-  evaluateJS(QString("waypts[%1].%2();\n")
-            .arg(i).arg(show?"show": "hide"));
-}
-
-//------------------------------------------------------------------------
-void Map::setTrackVisibility(int i, bool show)
-{
-  QString x = show?"show": "hide";
-  QStringList scriptStr;
-  scriptStr
-    << QString("trks[%1].%2();").arg(i).arg(x)
-    ;
-  evaluateJS(scriptStr);
-}
-
-//------------------------------------------------------------------------
-void Map::setRouteVisibility(int i, bool show)
-{
-  QString x = show?"show": "hide";
-  QStringList scriptStr;
-  scriptStr
-    << QString("rtes[%1].%2();").arg(i).arg(x)
-    ;
-  evaluateJS(scriptStr);
-}
-
-//------------------------------------------------------------------------
-void Map::panTo(const LatLng &loc)
-{
-  evaluateJS(QString("map.panTo(new GLatLng(%1));").arg(fmtLatLng(loc)));
-}
-
-//------------------------------------------------------------------------
-void Map::resizeEvent ( QResizeEvent * ev)
-{
-  QWebView::resizeEvent(ev);
-  if (mapPresent)
-    evaluateJS(QString("map.checkResize();"));
-}
-
-//------------------------------------------------------------------------
-void Map::setWaypointColorRed(int i)
-{
-  evaluateJS(QString("waypts[%1].setImage(redIcon.image)").arg(i));
-}
-
-//------------------------------------------------------------------------
-void Map::setWaypointColorBlue(int i)
-{
-  evaluateJS(QString("waypts[%1].setImage(blueIcon.image)").arg(i));
-}
-
-//------------------------------------------------------------------------
-void Map::frameTrack(int i)
-{
-  QStringList scriptStr;
-  scriptStr
-    << QString("var trkbound = trks[%1].getBounds();").arg(i)
-    << "map.setCenter(trkbound.getCenter(), map.getBoundsZoomLevel(trkbound));"
-    ;
-  evaluateJS(scriptStr);
-}
-
-
-//------------------------------------------------------------------------
-void Map::frameRoute(int i)
-{
-  QStringList scriptStr;
-  scriptStr
-    << QString("var rtebound = rtes[%1].getBounds();").arg(i)
-    << "map.setCenter(rtebound.getCenter(), map.getBoundsZoomLevel(rtebound));"
-    ;
-  evaluateJS(scriptStr);
-}
-
-
-//------------------------------------------------------------------------
-void Map::evaluateJS(const QString &s, bool upd)
-{
-  this->page()->mainFrame()->evaluateJavaScript(s);
-  if (upd) {
-    this->update();
-  }
-}
-
-//------------------------------------------------------------------------
-void Map::evaluateJS(const QStringList &s, bool upd)
-{
-  evaluateJS(s.join("\n"), upd);
-}
diff --git a/gpsbabel/gui/optionsdlg.cc b/gpsbabel/gui/optionsdlg.cc
new file mode 100644 (file)
index 0000000..b6564aa
--- /dev/null
@@ -0,0 +1,245 @@
+// -*- C++ -*-
+// $Id: optionsdlg.cpp,v 1.5 2010-03-01 04:22:28 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+
+#include <QVBoxLayout>
+#include <QDoubleValidator>
+#include <QIntValidator>
+#include <QPushButton>
+#include <QFileDialog>
+#include <QIcon>
+#include <QSpinBox>
+#include "optionsdlg.h"
+#include "help.h"
+
+//------------------------------------------------------------------------
+static void SetSizeStuff(QWidget *w)
+{
+  QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+  sizePolicy.setHorizontalStretch(0);
+  sizePolicy.setVerticalStretch(0);
+  sizePolicy.setHeightForWidth(w->sizePolicy().hasHeightForWidth());
+  w->setSizePolicy(sizePolicy);
+}
+
+//------------------------------------------------------------------------
+FileDlgManager::FileDlgManager(QObject*parent,
+                              QLineEdit *le,
+                              QToolButton *tb, bool isInFile):
+  QObject(parent), le(le), tb(tb), isInFile(isInFile)
+{
+  connect(tb, SIGNAL(clicked()), this, SLOT(buttonClicked()));
+}
+
+//------------------------------------------------------------------------
+QVariant getOptionValue(QList<FormatOption> opts, int k) {
+  if (opts[k].getValue().toString() != "")
+    return opts[k].getValue();
+  else
+    return opts[k].getDefaultValue();
+}
+
+//------------------------------------------------------------------------
+FileDlgManager::~FileDlgManager()
+{
+}
+//------------------------------------------------------------------------
+void FileDlgManager::buttonClicked()
+{
+  QString str;
+  if (isInFile) {
+    str = QFileDialog::getOpenFileName(0, tr("Select input file"),
+                                      le->text(),
+                                      "All Files (*.*)");
+  }
+  else {
+    str = QFileDialog::getSaveFileName(0, tr("Select output file"),
+                                      le->text(),
+                                      "All Files (*.*)");
+  }
+  if (str != "")
+    le->setText(str);
+}
+
+//------------------------------------------------------------------------
+OptionsDlg::OptionsDlg(QWidget*parent,  const QString &fmtName, QList<FormatOption> *opts,
+                      const QString &html):
+  QDialog(parent),
+  fmtName(fmtName),
+  options(*opts),
+  html(html)
+{
+
+  QVBoxLayout *verticalLayout = new QVBoxLayout(this);
+  for (int k=0; k<options.size(); k++) {
+    QHBoxLayout *horizontalLayout = new QHBoxLayout();
+
+    QCheckBox *checkBox = new QCheckBox(this);
+    checkBox->setText(tr(options[k].getDescription().toAscii().data()));
+    horizontalLayout->addWidget(checkBox);
+    checkBox->setChecked(options[k].getSelected());
+    //checkBox->setWhatsThis(options[k].getHtml());
+
+    QSpacerItem *horizontalSpacer = new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+    horizontalLayout->addItem(horizontalSpacer);
+
+    QWidget *w = 0;
+    switch (options[k].getType())
+      {
+      case FormatOption::OPTstring:
+       {
+         QLineEdit *lineEdit = new QLineEdit(this);
+         SetSizeStuff(lineEdit);
+         lineEdit->setText(getOptionValue(options, k).toString());
+         w = lineEdit;
+         horizontalLayout->addWidget(lineEdit);
+       }
+       break;
+
+      case FormatOption::OPTinFile:
+      case FormatOption::OPToutFile:
+       {
+         bool inFile = options[k].getType() == FormatOption::OPTinFile;
+         QLineEdit *lineEdit = new QLineEdit(this);
+         QToolButton *button = new QToolButton(this);
+         lineEdit->setText(getOptionValue(options, k).toString());
+         button->setIcon(QIcon(inFile ? ":images/file.png" : ":images/save.png" ));
+         w = lineEdit;
+         horizontalSpacer->changeSize(5, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);
+         horizontalLayout->addWidget(lineEdit);
+         horizontalLayout->addWidget(button);
+         (void) new FileDlgManager(this, lineEdit, button, inFile);
+       }
+       break;
+
+      case FormatOption::OPTbool:
+        // This is quirky.  It means that GPSBabel's bool options that default
+        // to true get turned on here, even if user turned them off on last
+        // exit.
+       checkBox->setChecked(getOptionValue(options,k).toBool());
+       w = 0;
+       break;
+
+      case FormatOption::OPTfloat:
+       {
+         QLineEdit *lineEdit = new QLineEdit(this);
+         SetSizeStuff(lineEdit);
+         lineEdit->setText(getOptionValue(options, k).toString());
+         w = lineEdit;
+         QDoubleValidator *v = new QDoubleValidator(this);
+         v->setRange(options[k].getMinValue().toDouble(),
+                     options[k].getMaxValue().toDouble());
+         lineEdit->setValidator(v);
+         horizontalLayout->addWidget(lineEdit);
+       }
+       break;
+
+      case FormatOption::OPTint:
+       {
+         QLineEdit *lineEdit = new QLineEdit(this);
+         SetSizeStuff(lineEdit);
+         w = lineEdit;
+         QIntValidator *iv = new QIntValidator(this);
+         iv->setRange(options[k].getMinValue().toInt(),
+                      options[k].getMaxValue().toInt());
+         lineEdit->setValidator(iv);
+         lineEdit->setText(getOptionValue(options, k).toString());
+         horizontalLayout->addWidget(lineEdit);
+       }
+       break;
+       
+      case FormatOption::OPTboundedInt:
+       {
+         QSpinBox *spinBox = new QSpinBox(this);
+         spinBox->setRange(options[k].getMinValue().toInt(),
+                           options[k].getMaxValue().toInt());
+         spinBox->setValue(getOptionValue(options, k).toInt());
+         SetSizeStuff(spinBox);
+         w = spinBox;
+         horizontalLayout->addWidget(spinBox);
+       }
+       break;
+      }
+    checkBoxes.push_back(checkBox);
+    fields.push_back(w);
+
+    verticalLayout->addLayout(horizontalLayout);
+  }
+  QPushButton *helpButton = new QPushButton(this);
+  helpButton->setIcon(QIcon(":/images/help.png"));
+  helpButton->setText(tr("Help"));
+
+  QHBoxLayout *lay = new QHBoxLayout();
+  lay->addWidget(helpButton);
+
+  buttonBox = new QDialogButtonBox(this);
+  buttonBox->setOrientation(Qt::Horizontal);
+  buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+  lay->addWidget(buttonBox);
+  verticalLayout->addLayout(lay);
+  buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":images/ok"));
+  buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":images/cancel"));
+
+  connect(buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
+  connect(buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
+  connect(helpButton, SIGNAL(clicked()), this,  SLOT(helpClicked()));
+}
+
+//------------------------------------------------------------------------
+void OptionsDlg::acceptClicked()
+{
+  for (int k=0; k<options.size(); k++) {
+    options[k].setSelected(checkBoxes[k]->isChecked());
+    if (fields[k]) {
+      if (options[k].getType() == FormatOption::OPTboundedInt) {
+       int value = static_cast<QSpinBox*>(fields[k])->value();
+       value = qMax(qMin(value, options[k].getMaxValue().toInt()),options[k].getMinValue().toInt());
+       options[k].setValue(QVariant(value));
+      }
+      else if (options[k].getType() == FormatOption::OPTint) {
+       int value = static_cast<QLineEdit*>(fields[k])->text().toInt();
+       value = qMax(qMin(value, options[k].getMaxValue().toInt()),options[k].getMinValue().toInt());
+       options[k].setValue(QVariant(value));
+      }
+      else if (options[k].getType() == FormatOption::OPTfloat) {
+       double value = static_cast<QLineEdit*>(fields[k])->text().toDouble();
+       value = qMax(qMin(value, options[k].getMaxValue().toDouble()),options[k].getMinValue().toDouble());
+       options[k].setValue(QVariant(value));
+      }
+      else
+       options[k].setValue(static_cast<QLineEdit*>(fields[k])->text());
+    }
+  }
+  accept();
+}
+
+//------------------------------------------------------------------------
+void OptionsDlg::rejectClicked()
+{
+  reject();
+}
+
+//------------------------------------------------------------------------
+void OptionsDlg::helpClicked()
+{
+  ShowHelp(html);
+}
diff --git a/gpsbabel/gui/optionsdlg.cpp b/gpsbabel/gui/optionsdlg.cpp
deleted file mode 100644 (file)
index b6564aa..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-// -*- C++ -*-
-// $Id: optionsdlg.cpp,v 1.5 2010-03-01 04:22:28 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-
-#include <QVBoxLayout>
-#include <QDoubleValidator>
-#include <QIntValidator>
-#include <QPushButton>
-#include <QFileDialog>
-#include <QIcon>
-#include <QSpinBox>
-#include "optionsdlg.h"
-#include "help.h"
-
-//------------------------------------------------------------------------
-static void SetSizeStuff(QWidget *w)
-{
-  QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
-  sizePolicy.setHorizontalStretch(0);
-  sizePolicy.setVerticalStretch(0);
-  sizePolicy.setHeightForWidth(w->sizePolicy().hasHeightForWidth());
-  w->setSizePolicy(sizePolicy);
-}
-
-//------------------------------------------------------------------------
-FileDlgManager::FileDlgManager(QObject*parent,
-                              QLineEdit *le,
-                              QToolButton *tb, bool isInFile):
-  QObject(parent), le(le), tb(tb), isInFile(isInFile)
-{
-  connect(tb, SIGNAL(clicked()), this, SLOT(buttonClicked()));
-}
-
-//------------------------------------------------------------------------
-QVariant getOptionValue(QList<FormatOption> opts, int k) {
-  if (opts[k].getValue().toString() != "")
-    return opts[k].getValue();
-  else
-    return opts[k].getDefaultValue();
-}
-
-//------------------------------------------------------------------------
-FileDlgManager::~FileDlgManager()
-{
-}
-//------------------------------------------------------------------------
-void FileDlgManager::buttonClicked()
-{
-  QString str;
-  if (isInFile) {
-    str = QFileDialog::getOpenFileName(0, tr("Select input file"),
-                                      le->text(),
-                                      "All Files (*.*)");
-  }
-  else {
-    str = QFileDialog::getSaveFileName(0, tr("Select output file"),
-                                      le->text(),
-                                      "All Files (*.*)");
-  }
-  if (str != "")
-    le->setText(str);
-}
-
-//------------------------------------------------------------------------
-OptionsDlg::OptionsDlg(QWidget*parent,  const QString &fmtName, QList<FormatOption> *opts,
-                      const QString &html):
-  QDialog(parent),
-  fmtName(fmtName),
-  options(*opts),
-  html(html)
-{
-
-  QVBoxLayout *verticalLayout = new QVBoxLayout(this);
-  for (int k=0; k<options.size(); k++) {
-    QHBoxLayout *horizontalLayout = new QHBoxLayout();
-
-    QCheckBox *checkBox = new QCheckBox(this);
-    checkBox->setText(tr(options[k].getDescription().toAscii().data()));
-    horizontalLayout->addWidget(checkBox);
-    checkBox->setChecked(options[k].getSelected());
-    //checkBox->setWhatsThis(options[k].getHtml());
-
-    QSpacerItem *horizontalSpacer = new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
-    horizontalLayout->addItem(horizontalSpacer);
-
-    QWidget *w = 0;
-    switch (options[k].getType())
-      {
-      case FormatOption::OPTstring:
-       {
-         QLineEdit *lineEdit = new QLineEdit(this);
-         SetSizeStuff(lineEdit);
-         lineEdit->setText(getOptionValue(options, k).toString());
-         w = lineEdit;
-         horizontalLayout->addWidget(lineEdit);
-       }
-       break;
-
-      case FormatOption::OPTinFile:
-      case FormatOption::OPToutFile:
-       {
-         bool inFile = options[k].getType() == FormatOption::OPTinFile;
-         QLineEdit *lineEdit = new QLineEdit(this);
-         QToolButton *button = new QToolButton(this);
-         lineEdit->setText(getOptionValue(options, k).toString());
-         button->setIcon(QIcon(inFile ? ":images/file.png" : ":images/save.png" ));
-         w = lineEdit;
-         horizontalSpacer->changeSize(5, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);
-         horizontalLayout->addWidget(lineEdit);
-         horizontalLayout->addWidget(button);
-         (void) new FileDlgManager(this, lineEdit, button, inFile);
-       }
-       break;
-
-      case FormatOption::OPTbool:
-        // This is quirky.  It means that GPSBabel's bool options that default
-        // to true get turned on here, even if user turned them off on last
-        // exit.
-       checkBox->setChecked(getOptionValue(options,k).toBool());
-       w = 0;
-       break;
-
-      case FormatOption::OPTfloat:
-       {
-         QLineEdit *lineEdit = new QLineEdit(this);
-         SetSizeStuff(lineEdit);
-         lineEdit->setText(getOptionValue(options, k).toString());
-         w = lineEdit;
-         QDoubleValidator *v = new QDoubleValidator(this);
-         v->setRange(options[k].getMinValue().toDouble(),
-                     options[k].getMaxValue().toDouble());
-         lineEdit->setValidator(v);
-         horizontalLayout->addWidget(lineEdit);
-       }
-       break;
-
-      case FormatOption::OPTint:
-       {
-         QLineEdit *lineEdit = new QLineEdit(this);
-         SetSizeStuff(lineEdit);
-         w = lineEdit;
-         QIntValidator *iv = new QIntValidator(this);
-         iv->setRange(options[k].getMinValue().toInt(),
-                      options[k].getMaxValue().toInt());
-         lineEdit->setValidator(iv);
-         lineEdit->setText(getOptionValue(options, k).toString());
-         horizontalLayout->addWidget(lineEdit);
-       }
-       break;
-       
-      case FormatOption::OPTboundedInt:
-       {
-         QSpinBox *spinBox = new QSpinBox(this);
-         spinBox->setRange(options[k].getMinValue().toInt(),
-                           options[k].getMaxValue().toInt());
-         spinBox->setValue(getOptionValue(options, k).toInt());
-         SetSizeStuff(spinBox);
-         w = spinBox;
-         horizontalLayout->addWidget(spinBox);
-       }
-       break;
-      }
-    checkBoxes.push_back(checkBox);
-    fields.push_back(w);
-
-    verticalLayout->addLayout(horizontalLayout);
-  }
-  QPushButton *helpButton = new QPushButton(this);
-  helpButton->setIcon(QIcon(":/images/help.png"));
-  helpButton->setText(tr("Help"));
-
-  QHBoxLayout *lay = new QHBoxLayout();
-  lay->addWidget(helpButton);
-
-  buttonBox = new QDialogButtonBox(this);
-  buttonBox->setOrientation(Qt::Horizontal);
-  buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
-  lay->addWidget(buttonBox);
-  verticalLayout->addLayout(lay);
-  buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":images/ok"));
-  buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":images/cancel"));
-
-  connect(buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
-  connect(buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
-  connect(helpButton, SIGNAL(clicked()), this,  SLOT(helpClicked()));
-}
-
-//------------------------------------------------------------------------
-void OptionsDlg::acceptClicked()
-{
-  for (int k=0; k<options.size(); k++) {
-    options[k].setSelected(checkBoxes[k]->isChecked());
-    if (fields[k]) {
-      if (options[k].getType() == FormatOption::OPTboundedInt) {
-       int value = static_cast<QSpinBox*>(fields[k])->value();
-       value = qMax(qMin(value, options[k].getMaxValue().toInt()),options[k].getMinValue().toInt());
-       options[k].setValue(QVariant(value));
-      }
-      else if (options[k].getType() == FormatOption::OPTint) {
-       int value = static_cast<QLineEdit*>(fields[k])->text().toInt();
-       value = qMax(qMin(value, options[k].getMaxValue().toInt()),options[k].getMinValue().toInt());
-       options[k].setValue(QVariant(value));
-      }
-      else if (options[k].getType() == FormatOption::OPTfloat) {
-       double value = static_cast<QLineEdit*>(fields[k])->text().toDouble();
-       value = qMax(qMin(value, options[k].getMaxValue().toDouble()),options[k].getMinValue().toDouble());
-       options[k].setValue(QVariant(value));
-      }
-      else
-       options[k].setValue(static_cast<QLineEdit*>(fields[k])->text());
-    }
-  }
-  accept();
-}
-
-//------------------------------------------------------------------------
-void OptionsDlg::rejectClicked()
-{
-  reject();
-}
-
-//------------------------------------------------------------------------
-void OptionsDlg::helpClicked()
-{
-  ShowHelp(html);
-}
diff --git a/gpsbabel/gui/preferences.cc b/gpsbabel/gui/preferences.cc
new file mode 100644 (file)
index 0000000..11fccf9
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Copyright (C) 2010  Robert Lipe  <robertlipe@gpsbabel.org>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+
+
+#include "preferences.h"
+#include "../gbversion.h"
+
+class FormatListEntry : public QListWidgetItem {
+ public:
+  FormatListEntry(Format& fmt) : fmt_(fmt)  {
+    setText(fmt.getDescription());
+    bool enabled = !fmt.isHidden();
+    setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
+  }
+
+ private:
+   Format& fmt_;
+};
+
+Preferences::Preferences(QWidget* parent, QList<Format>& formatList,
+                         BabelData& bd) : QDialog(parent),
+  formatList_(formatList),
+  bd_(bd)
+{
+  ui_.setupUi(this);
+
+  ui_.startupCheck->setChecked(bd_.startupVersionCheck);
+  ui_.reportStatisticsCheck->setChecked(bd_.reportStatistics);
+  ui_.ignoreVersionMismatchCheck->setChecked(bd_.ignoreVersionMismatch);
+  // Because of an unfortunate bug in 1.4.0, we turn this off in 1.4.1.
+  if (VERSION == QString("1.4.1"))
+    bd_.ignoreVersionMismatch = false;
+
+  connect (ui_.buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
+  connect (ui_.buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
+
+  connect (ui_.enableAllButton, SIGNAL(clicked()), this, SLOT(enableAllClicked()));
+  connect (ui_.disableAllButton, SIGNAL(clicked()), this, SLOT(disableAllClicked()));
+
+  for (int i = 0; i < formatList_.size(); i++) {
+    FormatListEntry *item = new FormatListEntry(formatList[i]);
+
+    ui_.enabledFormatsList->addItem(item);
+  }
+}
+
+void Preferences::enableAllClicked()
+{
+  for (int i = 0; i < ui_.enabledFormatsList->count(); i++) {
+    QListWidgetItem* item = ui_.enabledFormatsList->item(i);
+    item->setCheckState(Qt::Checked);
+  }
+}
+
+void Preferences::disableAllClicked()
+{
+  for (int i = 0; i < ui_.enabledFormatsList->count(); i++) {
+    QListWidgetItem* item = ui_.enabledFormatsList->item(i);
+    item->setCheckState(Qt::Unchecked);
+  }
+}
+
+void Preferences::acceptClicked()
+{
+  for (int i = 0; i < ui_.enabledFormatsList->count(); i++) {
+    QListWidgetItem* item = ui_.enabledFormatsList->item(i);
+    formatList_[i].setHidden(item->checkState() == Qt::Unchecked);
+  }
+
+  bd_.startupVersionCheck = ui_.startupCheck->isChecked();
+  bd_.reportStatistics = ui_.reportStatisticsCheck->isChecked();
+  bd_.ignoreVersionMismatch = ui_.ignoreVersionMismatchCheck->isChecked();
+  accept();
+}
+
+void Preferences::rejectClicked()
+{
+  reject();
+}
diff --git a/gpsbabel/gui/preferences.cpp b/gpsbabel/gui/preferences.cpp
deleted file mode 100644 (file)
index 11fccf9..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright (C) 2010  Robert Lipe  <robertlipe@gpsbabel.org>
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-
-
-#include "preferences.h"
-#include "../gbversion.h"
-
-class FormatListEntry : public QListWidgetItem {
- public:
-  FormatListEntry(Format& fmt) : fmt_(fmt)  {
-    setText(fmt.getDescription());
-    bool enabled = !fmt.isHidden();
-    setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
-  }
-
- private:
-   Format& fmt_;
-};
-
-Preferences::Preferences(QWidget* parent, QList<Format>& formatList,
-                         BabelData& bd) : QDialog(parent),
-  formatList_(formatList),
-  bd_(bd)
-{
-  ui_.setupUi(this);
-
-  ui_.startupCheck->setChecked(bd_.startupVersionCheck);
-  ui_.reportStatisticsCheck->setChecked(bd_.reportStatistics);
-  ui_.ignoreVersionMismatchCheck->setChecked(bd_.ignoreVersionMismatch);
-  // Because of an unfortunate bug in 1.4.0, we turn this off in 1.4.1.
-  if (VERSION == QString("1.4.1"))
-    bd_.ignoreVersionMismatch = false;
-
-  connect (ui_.buttonBox, SIGNAL(accepted()), this, SLOT(acceptClicked()));
-  connect (ui_.buttonBox, SIGNAL(rejected()), this, SLOT(rejectClicked()));
-
-  connect (ui_.enableAllButton, SIGNAL(clicked()), this, SLOT(enableAllClicked()));
-  connect (ui_.disableAllButton, SIGNAL(clicked()), this, SLOT(disableAllClicked()));
-
-  for (int i = 0; i < formatList_.size(); i++) {
-    FormatListEntry *item = new FormatListEntry(formatList[i]);
-
-    ui_.enabledFormatsList->addItem(item);
-  }
-}
-
-void Preferences::enableAllClicked()
-{
-  for (int i = 0; i < ui_.enabledFormatsList->count(); i++) {
-    QListWidgetItem* item = ui_.enabledFormatsList->item(i);
-    item->setCheckState(Qt::Checked);
-  }
-}
-
-void Preferences::disableAllClicked()
-{
-  for (int i = 0; i < ui_.enabledFormatsList->count(); i++) {
-    QListWidgetItem* item = ui_.enabledFormatsList->item(i);
-    item->setCheckState(Qt::Unchecked);
-  }
-}
-
-void Preferences::acceptClicked()
-{
-  for (int i = 0; i < ui_.enabledFormatsList->count(); i++) {
-    QListWidgetItem* item = ui_.enabledFormatsList->item(i);
-    formatList_[i].setHidden(item->checkState() == Qt::Unchecked);
-  }
-
-  bd_.startupVersionCheck = ui_.startupCheck->isChecked();
-  bd_.reportStatistics = ui_.reportStatisticsCheck->isChecked();
-  bd_.ignoreVersionMismatch = ui_.ignoreVersionMismatchCheck->isChecked();
-  accept();
-}
-
-void Preferences::rejectClicked()
-{
-  reject();
-}
diff --git a/gpsbabel/gui/processwait.cc b/gpsbabel/gui/processwait.cc
new file mode 100644 (file)
index 0000000..09669a9
--- /dev/null
@@ -0,0 +1,216 @@
+// -*- c++ -*-
+// $Id: processwait.cpp,v 1.3 2009-08-28 17:08:55 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+//------------------------------------------------------------------------
+#include <QProcess>
+#include <QStringList>
+#include <QPlainTextEdit>
+#include <QDialogButtonBox>
+#include <QVBoxLayout>
+#include <QDialog>
+#include <QProgressBar>
+#include <QPushButton>
+#include <QTimer>
+#include "processwait.h"
+#include "appname.h"
+
+
+//------------------------------------------------------------------------
+
+QString ProcessWaitDialog::processErrorString( QProcess::ProcessError err)
+{
+  switch (err)
+    {
+    case QProcess::FailedToStart:
+      return QString(tr("Process failed to start"));
+      break;
+    case QProcess::Crashed:
+      return QString(tr("Process crashed"));
+      break;
+    case QProcess::Timedout:
+      return QString(tr("Process timedout"));
+      break;
+    case QProcess::WriteError:
+      return QString(tr("Error while trying to write to process"));
+      break;
+    case QProcess::ReadError:
+      return QString(tr("Error while trying to read from process"));
+      break;
+    case QProcess::UnknownError:
+    default:
+      return QString(tr("Unknown process error"));
+    }
+  return QString("");
+}
+//------------------------------------------------------------------------
+ProcessWaitDialog::ProcessWaitDialog(QWidget *parent, QProcess *process):
+  QDialog(parent), process(process)
+{
+  this->resize(400, 220);
+  this->setWindowTitle(QString(appName) + tr(" ... Process GPSBabel"));
+  QVBoxLayout *layout = new QVBoxLayout(this);
+
+  textEdit = new QPlainTextEdit(this);
+  textEdit->setReadOnly(true);
+  layout->addWidget(textEdit);
+
+  progressBar = new QProgressBar(this);
+  progressBar->setTextVisible(false);
+  layout->addWidget(progressBar);
+
+  buttonBox = new QDialogButtonBox(this);
+  buttonBox->setOrientation(Qt::Horizontal);
+  buttonBox->setStandardButtons(QDialogButtonBox::Abort);
+  QPushButton* btn = buttonBox->button(QDialogButtonBox::Abort);
+  btn->setText(tr("Stop Process"));
+  layout->addWidget(buttonBox);
+
+  connect(process, SIGNAL(error(QProcess::ProcessError)),
+         this,    SLOT  (errorX(QProcess::ProcessError)));
+  connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
+         this,    SLOT  (finishedX(int, QProcess::ExitStatus)));
+  connect(process, SIGNAL(readyReadStandardError()),
+          this,    SLOT  (readyReadStandardErrorX()));
+  connect(process, SIGNAL(readyReadStandardOutput()),
+         this,    SLOT  (readyReadStandardOutputX()));
+  connect(btn,     SIGNAL(clicked()),
+         this,    SLOT  (stopClickedX()));
+  estatus = QProcess::CrashExit;  // Assume all errors are crashes for now.
+
+  bufferedOut = "";
+
+  //
+  for (int i=0; i<=100; i+=2)
+    progressVals.push_back(i);
+  for (int i=98; i>0; i-=2)
+    progressVals.push_back(i);
+  progressIndex = progressVals.size()/2;
+
+  timer = new QTimer(this);
+  timer->setInterval(100);
+  timer->setSingleShot(false);
+  connect(timer, SIGNAL(timeout()), this, SLOT(timeoutX()));
+  stopCount = -1;
+  timer->start();
+  errorString = "";
+
+}
+
+//------------------------------------------------------------------------
+ProcessWaitDialog::~ProcessWaitDialog()
+{
+};
+//------------------------------------------------------------------------
+bool ProcessWaitDialog::getExitedNormally()
+{
+  return (errorString.length() == 0);
+};
+
+//------------------------------------------------------------------------
+QString ProcessWaitDialog::getErrorString()
+{
+  return errorString;
+};
+
+//------------------------------------------------------------------------
+int ProcessWaitDialog::getExitCode()
+{
+  return ecode;
+};
+
+//------------------------------------------------------------------------
+void ProcessWaitDialog::stopClickedX()
+{
+  process->terminate();
+};
+//------------------------------------------------------------------------
+void ProcessWaitDialog::timeoutX()
+{
+  progressIndex++;
+  int idx = progressIndex % progressVals.size();
+  progressBar->setValue(progressVals[idx]);
+  if (stopCount >=0)
+    stopCount++;
+  if (stopCount > 150) {
+    process->kill();
+    errorString = QString(tr("Process did not terminate successfully"));
+    timer->stop();
+    accept();
+  }
+};
+
+//------------------------------------------------------------------------
+void ProcessWaitDialog::errorX(QProcess::ProcessError err)
+{
+  errorString = processErrorString(err);
+  timer->stop();
+  accept();
+};
+
+//------------------------------------------------------------------------
+void ProcessWaitDialog::finishedX(int exitCode, QProcess::ExitStatus es)
+{
+  ecode = exitCode;
+  if (es == QProcess::CrashExit)
+    errorString = QString(tr("Process crashed whle running"));
+  timer->stop();
+  accept();
+};
+
+
+//------------------------------------------------------------------------
+// appendPlainText automatically puts in a new line with every call.  That's
+// why you have to buffer it, and only append when we get a real newline.
+//
+void ProcessWaitDialog::appendToText(const char *ptr)
+{
+  outputString += QString(ptr);
+  for (const char *cptr = ptr; *cptr; cptr++) {
+    if (*cptr == '\r')
+      continue;
+    if (*cptr == '\n') {
+      textEdit->appendPlainText(QString::fromStdString(bufferedOut));
+      bufferedOut = "";
+      continue;
+    }
+    bufferedOut += *cptr;
+  }
+}
+
+
+//------------------------------------------------------------------------
+void ProcessWaitDialog::readyReadStandardErrorX()
+{
+  QByteArray d = process->readAllStandardError();
+  appendToText(d.data());
+};
+
+//------------------------------------------------------------------------
+void ProcessWaitDialog::readyReadStandardOutputX()
+ {
+  QByteArray d = process->readAllStandardOutput();
+  appendToText(d.data());
+};
+
+void ProcessWaitDialog::closeEvent(QCloseEvent *event)
+{
+   event->ignore();
+};
diff --git a/gpsbabel/gui/processwait.cpp b/gpsbabel/gui/processwait.cpp
deleted file mode 100644 (file)
index 09669a9..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-// -*- c++ -*-
-// $Id: processwait.cpp,v 1.3 2009-08-28 17:08:55 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-//------------------------------------------------------------------------
-#include <QProcess>
-#include <QStringList>
-#include <QPlainTextEdit>
-#include <QDialogButtonBox>
-#include <QVBoxLayout>
-#include <QDialog>
-#include <QProgressBar>
-#include <QPushButton>
-#include <QTimer>
-#include "processwait.h"
-#include "appname.h"
-
-
-//------------------------------------------------------------------------
-
-QString ProcessWaitDialog::processErrorString( QProcess::ProcessError err)
-{
-  switch (err)
-    {
-    case QProcess::FailedToStart:
-      return QString(tr("Process failed to start"));
-      break;
-    case QProcess::Crashed:
-      return QString(tr("Process crashed"));
-      break;
-    case QProcess::Timedout:
-      return QString(tr("Process timedout"));
-      break;
-    case QProcess::WriteError:
-      return QString(tr("Error while trying to write to process"));
-      break;
-    case QProcess::ReadError:
-      return QString(tr("Error while trying to read from process"));
-      break;
-    case QProcess::UnknownError:
-    default:
-      return QString(tr("Unknown process error"));
-    }
-  return QString("");
-}
-//------------------------------------------------------------------------
-ProcessWaitDialog::ProcessWaitDialog(QWidget *parent, QProcess *process):
-  QDialog(parent), process(process)
-{
-  this->resize(400, 220);
-  this->setWindowTitle(QString(appName) + tr(" ... Process GPSBabel"));
-  QVBoxLayout *layout = new QVBoxLayout(this);
-
-  textEdit = new QPlainTextEdit(this);
-  textEdit->setReadOnly(true);
-  layout->addWidget(textEdit);
-
-  progressBar = new QProgressBar(this);
-  progressBar->setTextVisible(false);
-  layout->addWidget(progressBar);
-
-  buttonBox = new QDialogButtonBox(this);
-  buttonBox->setOrientation(Qt::Horizontal);
-  buttonBox->setStandardButtons(QDialogButtonBox::Abort);
-  QPushButton* btn = buttonBox->button(QDialogButtonBox::Abort);
-  btn->setText(tr("Stop Process"));
-  layout->addWidget(buttonBox);
-
-  connect(process, SIGNAL(error(QProcess::ProcessError)),
-         this,    SLOT  (errorX(QProcess::ProcessError)));
-  connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
-         this,    SLOT  (finishedX(int, QProcess::ExitStatus)));
-  connect(process, SIGNAL(readyReadStandardError()),
-          this,    SLOT  (readyReadStandardErrorX()));
-  connect(process, SIGNAL(readyReadStandardOutput()),
-         this,    SLOT  (readyReadStandardOutputX()));
-  connect(btn,     SIGNAL(clicked()),
-         this,    SLOT  (stopClickedX()));
-  estatus = QProcess::CrashExit;  // Assume all errors are crashes for now.
-
-  bufferedOut = "";
-
-  //
-  for (int i=0; i<=100; i+=2)
-    progressVals.push_back(i);
-  for (int i=98; i>0; i-=2)
-    progressVals.push_back(i);
-  progressIndex = progressVals.size()/2;
-
-  timer = new QTimer(this);
-  timer->setInterval(100);
-  timer->setSingleShot(false);
-  connect(timer, SIGNAL(timeout()), this, SLOT(timeoutX()));
-  stopCount = -1;
-  timer->start();
-  errorString = "";
-
-}
-
-//------------------------------------------------------------------------
-ProcessWaitDialog::~ProcessWaitDialog()
-{
-};
-//------------------------------------------------------------------------
-bool ProcessWaitDialog::getExitedNormally()
-{
-  return (errorString.length() == 0);
-};
-
-//------------------------------------------------------------------------
-QString ProcessWaitDialog::getErrorString()
-{
-  return errorString;
-};
-
-//------------------------------------------------------------------------
-int ProcessWaitDialog::getExitCode()
-{
-  return ecode;
-};
-
-//------------------------------------------------------------------------
-void ProcessWaitDialog::stopClickedX()
-{
-  process->terminate();
-};
-//------------------------------------------------------------------------
-void ProcessWaitDialog::timeoutX()
-{
-  progressIndex++;
-  int idx = progressIndex % progressVals.size();
-  progressBar->setValue(progressVals[idx]);
-  if (stopCount >=0)
-    stopCount++;
-  if (stopCount > 150) {
-    process->kill();
-    errorString = QString(tr("Process did not terminate successfully"));
-    timer->stop();
-    accept();
-  }
-};
-
-//------------------------------------------------------------------------
-void ProcessWaitDialog::errorX(QProcess::ProcessError err)
-{
-  errorString = processErrorString(err);
-  timer->stop();
-  accept();
-};
-
-//------------------------------------------------------------------------
-void ProcessWaitDialog::finishedX(int exitCode, QProcess::ExitStatus es)
-{
-  ecode = exitCode;
-  if (es == QProcess::CrashExit)
-    errorString = QString(tr("Process crashed whle running"));
-  timer->stop();
-  accept();
-};
-
-
-//------------------------------------------------------------------------
-// appendPlainText automatically puts in a new line with every call.  That's
-// why you have to buffer it, and only append when we get a real newline.
-//
-void ProcessWaitDialog::appendToText(const char *ptr)
-{
-  outputString += QString(ptr);
-  for (const char *cptr = ptr; *cptr; cptr++) {
-    if (*cptr == '\r')
-      continue;
-    if (*cptr == '\n') {
-      textEdit->appendPlainText(QString::fromStdString(bufferedOut));
-      bufferedOut = "";
-      continue;
-    }
-    bufferedOut += *cptr;
-  }
-}
-
-
-//------------------------------------------------------------------------
-void ProcessWaitDialog::readyReadStandardErrorX()
-{
-  QByteArray d = process->readAllStandardError();
-  appendToText(d.data());
-};
-
-//------------------------------------------------------------------------
-void ProcessWaitDialog::readyReadStandardOutputX()
- {
-  QByteArray d = process->readAllStandardOutput();
-  appendToText(d.data());
-};
-
-void ProcessWaitDialog::closeEvent(QCloseEvent *event)
-{
-   event->ignore();
-};
diff --git a/gpsbabel/gui/serial_mac.cc b/gpsbabel/gui/serial_mac.cc
new file mode 100644 (file)
index 0000000..fc78d9c
--- /dev/null
@@ -0,0 +1,214 @@
+// Borrowed liberally (as allowed by license) from
+// http://developer.apple.com/samplecode/SerialPortSample/index.html
+// This really is a slash-and-burn; no attempt was to make it very "C++-iike"
+
+// Apple's copyright blob:
+/*
+    Copyright:         Â© Copyright 2000-2005 Apple Computer, Inc. All rights reserved.
+       
+    Disclaimer:                IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                                       ("Apple") in consideration of your agreement to the following terms, and your
+                                       use, installation, modification or redistribution of this Apple software
+                                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                                       please do not use, install, modify or redistribute this Apple software.
+
+                                       In consideration of your agreement to abide by the following terms, and subject
+                                       to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+                                       copyrights in this original Apple software (the "Apple Software"), to use,
+                                       reproduce, modify and redistribute the Apple Software, with or without
+                                       modifications, in source and/or binary forms; provided that if you redistribute
+                                       the Apple Software in its entirety and without modifications, you must retain
+                                       this notice and the following text and disclaimers in all such redistributions of
+                                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                                       Apple Software without specific prior written permission from Apple.  Except as
+                                       expressly stated in this notice, no other rights or licenses, express or implied,
+                                       are granted by Apple herein, including but not limited to any patent rights that
+                                       may be infringed by your derivative works or by other works in which the Apple
+                                       Software may be incorporated.
+
+                                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                                       COMBINATION WITH YOUR PRODUCTS.
+
+                                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+                               
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <paths.h>
+#include <termios.h>
+#include <sysexits.h>
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <time.h>
+#include <AvailabilityMacros.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
+#include <IOKit/serial/ioss.h>
+#endif
+#include <IOKit/IOBSD.h>
+
+#include "mainwindow.h"
+
+// Function prototypes
+static kern_return_t FindModems(io_iterator_t *matchingServices);
+// static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize);
+// static int OpenSerialPort(const char *bsdPath);
+
+// Returns an iterator across all known modems. Caller is responsible for
+// releasing the iterator when iteration is complete.
+static kern_return_t FindModems(io_iterator_t *matchingServices)
+{
+    kern_return_t                      kernResult;
+    CFMutableDictionaryRef     classesToMatch;
+
+/*! @function IOServiceMatching
+    @abstract Create a matching dictionary that specifies an IOService class match.
+    @discussion A very common matching criteria for IOService is based on its class. IOServiceMatching will create a matching dictionary that specifies any IOService of a class, or its subclasses. The class is specified by C-string name.
+    @param name The class name, as a const C-string. Class matching is successful on IOService's of this class or any subclass.
+    @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */
+
+    // Serial devices are instances of class IOSerialBSDClient
+    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
+    if (classesToMatch == NULL)
+    {
+        printf("IOServiceMatching returned a NULL dictionary.\n");
+    }
+    else {
+/*!
+       @function CFDictionarySetValue
+       Sets the value of the key in the dictionary.
+       @param theDict The dictionary to which the value is to be set. If this
+               parameter is not a valid mutable CFDictionary, the behavior is
+               undefined. If the dictionary is a fixed-capacity dictionary and
+               it is full before this operation, and the key does not exist in
+               the dictionary, the behavior is undefined.
+       @param key The key of the value to set into the dictionary. If a key
+               which matches this key is already present in the dictionary, only
+               the value is changed ("add if absent, replace if present"). If
+               no key matches the given key, the key-value pair is added to the
+               dictionary. If added, the key is retained by the dictionary,
+               using the retain callback provided
+               when the dictionary was created. If the key is not of the sort
+               expected by the key retain callback, the behavior is undefined.
+       @param value The value to add to or replace into the dictionary. The value
+               is retained by the dictionary using the retain callback provided
+               when the dictionary was created, and the previous value if any is
+               released. If the value is not of the sort expected by the
+               retain or release callbacks, the behavior is undefined.
+*/
+//        CFDictionarySetValue(classesToMatch,
+//                             CFSTR(kIOSerialBSDTypeKey),
+//                             CFSTR(kIOSerialBSDModemType));
+
+               // Each serial device object has a property with key
+        // kIOSerialBSDTypeKey and a value that is one of kIOSerialBSDAllTypes,
+        // kIOSerialBSDModemType, or kIOSerialBSDRS232Type. You can experiment with the
+        // matching by changing the last parameter in the above call to CFDictionarySetValue.
+
+        // As shipped, this sample is only interested in modems,
+        // so add this property to the CFDictionary we're matching on.
+        // This will find devices that advertise themselves as modems,
+        // such as built-in and USB modems. However, this match won't find serial modems.
+    }
+
+    /*! @function IOServiceGetMatchingServices
+        @abstract Look up registered IOService objects that match a matching dictionary.
+        @discussion This is the preferred method of finding IOService objects currently registered by IOKit. IOServiceAddNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up.
+        @param masterPort The master port obtained from IOMasterPort().
+        @param matching A CF dictionary containing matching information, of which one reference is consumed by this function. IOKitLib can contruct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOOpenFirmwarePathMatching.
+        @param existing An iterator handle is returned on success, and should be released by the caller when the iteration is finished.
+        @result A kern_return_t error code. */
+
+    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
+    if (KERN_SUCCESS != kernResult)
+    {
+        printf("IOServiceGetMatchingServices returned %d\n", kernResult);
+               goto exit;
+    }
+
+exit:
+    return kernResult;
+}
+
+// Given an iterator across a set of modems, return the BSD path to the first one.
+// If no modems are found the path name is set to an empty string.
+static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize, QComboBox *box)
+{
+    io_object_t                modemService;
+    kern_return_t      kernResult = KERN_FAILURE;
+    Boolean                    modemFound = false;
+
+    // Initialize the returned path
+    *bsdPath = '\0';
+
+    // Iterate across all modems found. In this example, we bail after finding the first modem.
+
+    while ((modemService = IOIteratorNext(serialPortIterator)) && !modemFound)
+    {
+        CFTypeRef      bsdPathAsCFString;
+
+               // Get the callout device's path (/dev/cu.xxxxx). The callout device should almost always be
+               // used: the dialin device (/dev/tty.xxxxx) would be used when monitoring a serial port for
+               // incoming calls, e.g. a fax listener.
+       
+               bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService,
+                                                            CFSTR(kIOCalloutDeviceKey),
+                                                            kCFAllocatorDefault,
+                                                            0);
+        if (bsdPathAsCFString)
+        {
+            Boolean result;
+
+            // Convert the path from a CFString to a C (NUL-terminated) string for use
+                       // with the POSIX open() call.
+       
+                       result = CFStringGetCString((const __CFString*) bsdPathAsCFString,
+                                        bsdPath,
+                                        maxPathSize,
+                                        kCFStringEncodingUTF8);
+            CFRelease(bsdPathAsCFString);
+
+            if (result) {
+                   box->addItem(bsdPath);
+            }
+        }
+
+        // Release the io_service_t now that we are done with it.
+       
+//             (void) IOObjectRelease(modemService);
+    }
+
+    return kernResult;
+}
+
+#include "mainwindow.h"
+void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
+{
+  kern_return_t       kernResult;
+  io_iterator_t       serialPortIterator;
+  char                bsdPath[MAXPATHLEN];
+
+  kernResult = FindModems(&serialPortIterator);
+  kernResult = GetModemPath(serialPortIterator, bsdPath, sizeof(bsdPath), box);
+
+}
diff --git a/gpsbabel/gui/serial_mac.cpp b/gpsbabel/gui/serial_mac.cpp
deleted file mode 100644 (file)
index fc78d9c..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-// Borrowed liberally (as allowed by license) from
-// http://developer.apple.com/samplecode/SerialPortSample/index.html
-// This really is a slash-and-burn; no attempt was to make it very "C++-iike"
-
-// Apple's copyright blob:
-/*
-    Copyright:         Â© Copyright 2000-2005 Apple Computer, Inc. All rights reserved.
-       
-    Disclaimer:                IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-                                       ("Apple") in consideration of your agreement to the following terms, and your
-                                       use, installation, modification or redistribution of this Apple software
-                                       constitutes acceptance of these terms.  If you do not agree with these terms,
-                                       please do not use, install, modify or redistribute this Apple software.
-
-                                       In consideration of your agreement to abide by the following terms, and subject
-                                       to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
-                                       copyrights in this original Apple software (the "Apple Software"), to use,
-                                       reproduce, modify and redistribute the Apple Software, with or without
-                                       modifications, in source and/or binary forms; provided that if you redistribute
-                                       the Apple Software in its entirety and without modifications, you must retain
-                                       this notice and the following text and disclaimers in all such redistributions of
-                                       the Apple Software.  Neither the name, trademarks, service marks or logos of
-                                       Apple Computer, Inc. may be used to endorse or promote products derived from the
-                                       Apple Software without specific prior written permission from Apple.  Except as
-                                       expressly stated in this notice, no other rights or licenses, express or implied,
-                                       are granted by Apple herein, including but not limited to any patent rights that
-                                       may be infringed by your derivative works or by other works in which the Apple
-                                       Software may be incorporated.
-
-                                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-                                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-                                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-                                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-                                       COMBINATION WITH YOUR PRODUCTS.
-
-                                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-                                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-                                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-                                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-                                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-                                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-                                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-                               
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <paths.h>
-#include <termios.h>
-#include <sysexits.h>
-#include <sys/param.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <time.h>
-#include <AvailabilityMacros.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/serial/IOSerialKeys.h>
-#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
-#include <IOKit/serial/ioss.h>
-#endif
-#include <IOKit/IOBSD.h>
-
-#include "mainwindow.h"
-
-// Function prototypes
-static kern_return_t FindModems(io_iterator_t *matchingServices);
-// static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize);
-// static int OpenSerialPort(const char *bsdPath);
-
-// Returns an iterator across all known modems. Caller is responsible for
-// releasing the iterator when iteration is complete.
-static kern_return_t FindModems(io_iterator_t *matchingServices)
-{
-    kern_return_t                      kernResult;
-    CFMutableDictionaryRef     classesToMatch;
-
-/*! @function IOServiceMatching
-    @abstract Create a matching dictionary that specifies an IOService class match.
-    @discussion A very common matching criteria for IOService is based on its class. IOServiceMatching will create a matching dictionary that specifies any IOService of a class, or its subclasses. The class is specified by C-string name.
-    @param name The class name, as a const C-string. Class matching is successful on IOService's of this class or any subclass.
-    @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */
-
-    // Serial devices are instances of class IOSerialBSDClient
-    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
-    if (classesToMatch == NULL)
-    {
-        printf("IOServiceMatching returned a NULL dictionary.\n");
-    }
-    else {
-/*!
-       @function CFDictionarySetValue
-       Sets the value of the key in the dictionary.
-       @param theDict The dictionary to which the value is to be set. If this
-               parameter is not a valid mutable CFDictionary, the behavior is
-               undefined. If the dictionary is a fixed-capacity dictionary and
-               it is full before this operation, and the key does not exist in
-               the dictionary, the behavior is undefined.
-       @param key The key of the value to set into the dictionary. If a key
-               which matches this key is already present in the dictionary, only
-               the value is changed ("add if absent, replace if present"). If
-               no key matches the given key, the key-value pair is added to the
-               dictionary. If added, the key is retained by the dictionary,
-               using the retain callback provided
-               when the dictionary was created. If the key is not of the sort
-               expected by the key retain callback, the behavior is undefined.
-       @param value The value to add to or replace into the dictionary. The value
-               is retained by the dictionary using the retain callback provided
-               when the dictionary was created, and the previous value if any is
-               released. If the value is not of the sort expected by the
-               retain or release callbacks, the behavior is undefined.
-*/
-//        CFDictionarySetValue(classesToMatch,
-//                             CFSTR(kIOSerialBSDTypeKey),
-//                             CFSTR(kIOSerialBSDModemType));
-
-               // Each serial device object has a property with key
-        // kIOSerialBSDTypeKey and a value that is one of kIOSerialBSDAllTypes,
-        // kIOSerialBSDModemType, or kIOSerialBSDRS232Type. You can experiment with the
-        // matching by changing the last parameter in the above call to CFDictionarySetValue.
-
-        // As shipped, this sample is only interested in modems,
-        // so add this property to the CFDictionary we're matching on.
-        // This will find devices that advertise themselves as modems,
-        // such as built-in and USB modems. However, this match won't find serial modems.
-    }
-
-    /*! @function IOServiceGetMatchingServices
-        @abstract Look up registered IOService objects that match a matching dictionary.
-        @discussion This is the preferred method of finding IOService objects currently registered by IOKit. IOServiceAddNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up.
-        @param masterPort The master port obtained from IOMasterPort().
-        @param matching A CF dictionary containing matching information, of which one reference is consumed by this function. IOKitLib can contruct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOOpenFirmwarePathMatching.
-        @param existing An iterator handle is returned on success, and should be released by the caller when the iteration is finished.
-        @result A kern_return_t error code. */
-
-    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
-    if (KERN_SUCCESS != kernResult)
-    {
-        printf("IOServiceGetMatchingServices returned %d\n", kernResult);
-               goto exit;
-    }
-
-exit:
-    return kernResult;
-}
-
-// Given an iterator across a set of modems, return the BSD path to the first one.
-// If no modems are found the path name is set to an empty string.
-static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize, QComboBox *box)
-{
-    io_object_t                modemService;
-    kern_return_t      kernResult = KERN_FAILURE;
-    Boolean                    modemFound = false;
-
-    // Initialize the returned path
-    *bsdPath = '\0';
-
-    // Iterate across all modems found. In this example, we bail after finding the first modem.
-
-    while ((modemService = IOIteratorNext(serialPortIterator)) && !modemFound)
-    {
-        CFTypeRef      bsdPathAsCFString;
-
-               // Get the callout device's path (/dev/cu.xxxxx). The callout device should almost always be
-               // used: the dialin device (/dev/tty.xxxxx) would be used when monitoring a serial port for
-               // incoming calls, e.g. a fax listener.
-       
-               bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService,
-                                                            CFSTR(kIOCalloutDeviceKey),
-                                                            kCFAllocatorDefault,
-                                                            0);
-        if (bsdPathAsCFString)
-        {
-            Boolean result;
-
-            // Convert the path from a CFString to a C (NUL-terminated) string for use
-                       // with the POSIX open() call.
-       
-                       result = CFStringGetCString((const __CFString*) bsdPathAsCFString,
-                                        bsdPath,
-                                        maxPathSize,
-                                        kCFStringEncodingUTF8);
-            CFRelease(bsdPathAsCFString);
-
-            if (result) {
-                   box->addItem(bsdPath);
-            }
-        }
-
-        // Release the io_service_t now that we are done with it.
-       
-//             (void) IOObjectRelease(modemService);
-    }
-
-    return kernResult;
-}
-
-#include "mainwindow.h"
-void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
-{
-  kern_return_t       kernResult;
-  io_iterator_t       serialPortIterator;
-  char                bsdPath[MAXPATHLEN];
-
-  kernResult = FindModems(&serialPortIterator);
-  kernResult = GetModemPath(serialPortIterator, bsdPath, sizeof(bsdPath), box);
-
-}
diff --git a/gpsbabel/gui/serial_unix.cc b/gpsbabel/gui/serial_unix.cc
new file mode 100644 (file)
index 0000000..6c65bd0
--- /dev/null
@@ -0,0 +1,40 @@
+// $Id: serial_unix.cpp,v 1.2 2010-02-13 23:25:23 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+#include "mainwindow.h"
+#if !defined (Q_OS_MAC) // FIXME: find a better way to hide this on Mac.
+
+static const char *deviceNames[] = {
+  "/dev/ttyS0",
+  "/dev/ttyS1",
+  "/dev/ttyS2",
+  "/dev/ttyS3",
+  "/dev/ttyUSB0",
+  "/dev/rfcomm0",
+  0
+};
+
+void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
+{
+  for (int i=0; deviceNames[i]; i++) {
+    box->addItem(deviceNames[i]);
+  }
+}
+#endif
diff --git a/gpsbabel/gui/serial_unix.cpp b/gpsbabel/gui/serial_unix.cpp
deleted file mode 100644 (file)
index 6c65bd0..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// $Id: serial_unix.cpp,v 1.2 2010-02-13 23:25:23 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-#include "mainwindow.h"
-#if !defined (Q_OS_MAC) // FIXME: find a better way to hide this on Mac.
-
-static const char *deviceNames[] = {
-  "/dev/ttyS0",
-  "/dev/ttyS1",
-  "/dev/ttyS2",
-  "/dev/ttyS3",
-  "/dev/ttyUSB0",
-  "/dev/rfcomm0",
-  0
-};
-
-void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
-{
-  for (int i=0; deviceNames[i]; i++) {
-    box->addItem(deviceNames[i]);
-  }
-}
-#endif
diff --git a/gpsbabel/gui/serial_win.cc b/gpsbabel/gui/serial_win.cc
new file mode 100644 (file)
index 0000000..7ebf025
--- /dev/null
@@ -0,0 +1,72 @@
+// $Id: serial_win.cpp,v 1.3 2010-06-21 02:35:06 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+
+#include "mainwindow.h"
+
+#if 0  // Does not require Windows 2000
+
+static const char *deviceNames[] = {
+  "com1:",
+  "com2:",
+  "com3:",
+  "com4:",
+  0
+};
+
+void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
+{
+  for (int i=0; deviceNames[i]; i++) {
+    box->addItem(deviceNames[i]);
+  }
+}
+
+#else // This code assumes Windows 2000 or later
+
+// Uses QueryDosDevice(), Minimum supported: Windows 2000 Professional/Server
+#include <Windows.h> 
+#include <stdio.h>
+
+void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
+{
+  char DevList[64*1024-1];  // a single byte more, and certain versions of windows
+                            // always return QueryDosDevice()==0 && GetLastError()==ERROR_MORE_DATA.
+                            // see http://support.microsoft.com/kb/931305
+  // Get a list of all existing MS-DOS device names. Stores one or more asciiz strings followed by an extra null.
+  DWORD res = QueryDosDeviceA(NULL, DevList, sizeof(DevList));
+  if (res == 0)
+  {
+    DWORD err = GetLastError(); // could check for ERROR_INSUFFICIENT_BUFFER, and retry with a larger buffer.
+                                // but DevList is already at the maximum size it can be without running into kb 931305.
+    // FIXME: This shold be a QMessageBox::warning() - RJL
+    // fprintf(stderr,"QueryDosDevice() failed with %d.  GetLastError()==%d.\n", res, err);
+    (void) err;
+    return;
+  }
+
+  for (char *p=DevList; *p;) {
+    int len = strlen(p);
+    if (strncmp(p,"COM",3)==0)
+      box->addItem((PCHAR)p);
+    p += len+1; // +1 to also skip the null character of each string
+  }
+}
+
+#endif
diff --git a/gpsbabel/gui/serial_win.cpp b/gpsbabel/gui/serial_win.cpp
deleted file mode 100644 (file)
index 7ebf025..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// $Id: serial_win.cpp,v 1.3 2010-06-21 02:35:06 robertl Exp $
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-
-#include "mainwindow.h"
-
-#if 0  // Does not require Windows 2000
-
-static const char *deviceNames[] = {
-  "com1:",
-  "com2:",
-  "com3:",
-  "com4:",
-  0
-};
-
-void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
-{
-  for (int i=0; deviceNames[i]; i++) {
-    box->addItem(deviceNames[i]);
-  }
-}
-
-#else // This code assumes Windows 2000 or later
-
-// Uses QueryDosDevice(), Minimum supported: Windows 2000 Professional/Server
-#include <Windows.h> 
-#include <stdio.h>
-
-void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
-{
-  char DevList[64*1024-1];  // a single byte more, and certain versions of windows
-                            // always return QueryDosDevice()==0 && GetLastError()==ERROR_MORE_DATA.
-                            // see http://support.microsoft.com/kb/931305
-  // Get a list of all existing MS-DOS device names. Stores one or more asciiz strings followed by an extra null.
-  DWORD res = QueryDosDeviceA(NULL, DevList, sizeof(DevList));
-  if (res == 0)
-  {
-    DWORD err = GetLastError(); // could check for ERROR_INSUFFICIENT_BUFFER, and retry with a larger buffer.
-                                // but DevList is already at the maximum size it can be without running into kb 931305.
-    // FIXME: This shold be a QMessageBox::warning() - RJL
-    // fprintf(stderr,"QueryDosDevice() failed with %d.  GetLastError()==%d.\n", res, err);
-    (void) err;
-    return;
-  }
-
-  for (char *p=DevList; *p;) {
-    int len = strlen(p);
-    if (strncmp(p,"COM",3)==0)
-      box->addItem((PCHAR)p);
-    p += len+1; // +1 to also skip the null character of each string
-  }
-}
-
-#endif
diff --git a/gpsbabel/gui/upgrade.cc b/gpsbabel/gui/upgrade.cc
new file mode 100644 (file)
index 0000000..6a7ecd6
--- /dev/null
@@ -0,0 +1,322 @@
+// -*- C++ -*-
+// $Id: upgrade.cpp,v 1.26 2010-06-19 23:59:06 robertl Exp $
+/*
+    Copyright (C) 2009, 2010  Robert Lipe, robertlipe@gpsbabel.org
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+
+#include "babeldata.h"
+#include "format.h"
+#include "upgrade.h"
+#include "../gbversion.h"
+#if HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#if HAVE_UNAME
+#include <sys/utsname.h>
+#endif // HAVE_UNAME
+
+#include <QHttp>
+#include <QMessageBox>
+#include <QDesktopServices>
+#include <QDomDocument>
+#include <QLocale>
+#include <QSysInfo>
+#include <QUrl>
+#include <stdio.h>
+
+#if 0
+static const bool testing = true;
+#else
+static const bool testing = false;
+#endif
+
+UpgradeCheck::UpgradeCheck(QWidget *parent, QList<Format> &formatList,
+                           BabelData& bd) :
+  QObject(parent),
+  http(0), 
+  formatList_(formatList), 
+  updateStatus_(updateUnknown),
+  bd_(bd)
+{
+}
+
+UpgradeCheck::~UpgradeCheck()
+{
+  if (http) {
+    http->clearPendingRequests();
+    http->abort();
+    delete http;
+    http = 0;
+  }
+}
+
+bool UpgradeCheck::isTestMode()
+{
+  return testing;
+}
+
+QString UpgradeCheck::getOsName(void)
+{
+  // Do not translate these strings.
+#if defined (Q_OS_LINUX)
+    return "Linux";
+#elif defined (Q_OS_MAC)
+  return "Mac";
+#elif defined (Q_OS_WIN)
+  return "Windows";
+#else
+  return "Unknown";
+#endif
+
+}
+// See http://doc.trolltech.com/4.5/qsysinfo.html to interpret results
+QString UpgradeCheck::getOsVersion()
+{
+#if defined (Q_OS_MAC)
+  switch (QSysInfo::MacintoshVersion) {
+  case QSysInfo::MV_10_3: return "10.3"; break;
+  case QSysInfo::MV_10_4: return "10.4"; break;
+  case QSysInfo::MV_10_5: return "10.5"; break;
+  case QSysInfo::MV_10_6: return "10.6"; break;
+  case QSysInfo::MV_10_7: return "10.7"; break;
+  //case QSysInfo::MV_10_8: return "10.8"; break;
+  default: 
+    if (QSysInfo::MacintoshVersion == 10) {
+      return "10.8";
+      break;
+    }
+    return QString("Unknown Mac %1").arg(QSysInfo::MacintoshVersion);
+  };
+#elif defined (Q_OS_WIN)
+
+  switch (QSysInfo::WindowsVersion) {
+  // Wildly improbable...
+  case QSysInfo::WV_95: return "95"; break;
+  case QSysInfo::WV_98: return "98"; break;
+  case QSysInfo::WV_Me: return "Me"; break;
+
+  case QSysInfo::WV_4_0: return "NT 4"; break;
+  case QSysInfo::WV_5_0: return "2000"; break;
+  case QSysInfo::WV_5_1: return "XP"; break;
+  case QSysInfo::WV_5_2: return "2003"; break;
+  case QSysInfo::WV_6_0: return "Vista"; break;
+  case QSysInfo::WV_6_1: return "7"; break;
+  default:
+      return "Windows/Unknown";
+  }
+#endif
+  // FIXME: find something appropriately clever to do for Linux, etc. here.
+  return "Unknown";
+}
+
+
+UpgradeCheck::updateStatus UpgradeCheck::checkForUpgrade(
+               const QString &currentVersionIn,
+               const QDateTime &lastCheckTime,
+               bool allowBeta)
+{
+  currentVersion = currentVersionIn;
+  currentVersion.remove("GPSBabel Version ");
+
+  QDateTime soonestCheckTime = lastCheckTime.addDays(1);
+  if (!testing && QDateTime::currentDateTime() < soonestCheckTime) {
+    // Not time to check yet.
+    return UpgradeCheck::updateUnknown;
+  }
+
+  http = new QHttp;
+
+  connect(http, SIGNAL(requestFinished(int, bool)),
+          this, SLOT(httpRequestFinished(int, bool)));
+  connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
+          this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
+
+  QHttpRequestHeader header("POST", "/upgrade_check.html");
+
+  const QString host("www.gpsbabel.org" );
+  header.setValue("Host",  host);
+
+  header.setContentType("application/x-www-form-urlencoded");
+  QLocale locale;
+
+  QString args = "current_version=" + currentVersion;
+  args += "&current_gui_version=" VERSION;
+  args += "&installation=" + bd_.installationUuid;
+  args += "&os=" + getOsName();
+#if HAVE_UNAME
+  struct utsname utsname;
+  if (0 == uname(&utsname)) {
+    args += "&cpu=" + QString(utsname.machine);
+  }
+#endif
+
+  args += "&os_ver=" + getOsVersion();
+  args += QString("&beta_ok=%1").arg(allowBeta); 
+  args += "&lang=" + QLocale::languageToString(locale.language());
+  args += "&last_checkin=" + lastCheckTime.toString(Qt::ISODate);
+  args += QString("&ugcb=%1").arg(bd_.upgradeCallbacks); 
+  args += QString("&ugdec=%1").arg(bd_.upgradeDeclines); 
+  args += QString("&ugacc=%1").arg(bd_.upgradeAccept); 
+  args += QString("&ugoff=%1").arg(bd_.upgradeOffers); 
+  args += QString("&ugerr=%1").arg(bd_.upgradeErrors); 
+  args += QString("&rc=%1").arg(bd_.runCount); 
+
+  int j = 0;
+
+  for (int i = 0; i < formatList_.size(); i++) {
+    int rc = formatList_[i].getReadUseCount();
+    int wc = formatList_[i].getWriteUseCount();
+    QString formatName = formatList_[i].getName();
+    if (rc)
+      args += QString("&uc%1=rd/%2/%3").arg(j++).arg(formatName).arg(rc);
+    if (wc)
+      args += QString("&uc%1=wr/%2/%3").arg(j++).arg(formatName).arg(wc);
+  }
+  if (j && bd_.reportStatistics)
+    args += QString("&uc=%1").arg(j);
+
+  if (false && testing)
+   fprintf(stderr, "Posting %s\n", qPrintable(args));
+
+  http->setHost(host, 80);
+  httpRequestId = http->request(header, args.toUtf8());
+
+  return UpgradeCheck::updateUnknown;
+}
+
+void UpgradeCheck::readResponseHeader(const QHttpResponseHeader &responseHeader)
+{
+  switch (responseHeader.statusCode()) {
+  case 200:                   // Ok
+  case 301:                   // Moved Permanently
+  case 302:                   // Found
+  case 303:                   // See Other
+  case 307:                   // Temporary Redirect
+    // these are not error conditions
+    break;
+
+  default:
+    QMessageBox::information(0, tr("HTTP"),
+           tr("Download failed: %1.")
+           .arg(responseHeader.reasonPhrase()));
+    httpRequestAborted = true;
+    http->abort();
+  }
+}
+
+void UpgradeCheck::httpRequestFinished(int requestId, bool error)
+{
+
+  if (http == 0 || error) {
+    bd_.upgradeErrors++;
+    return;
+  }
+
+  // This is not an error state; it's just the internal state of Qt's network
+  // stack flailing around.
+  if (requestId != httpRequestId) {
+    return;
+  }
+
+  bd_.upgradeCallbacks++;
+  QString oresponse(http->readAll());
+
+  QDomDocument document;
+  int line = -1;
+  QString error_text;
+  // This shouldn't ever be seen by a user.  
+  if (!document.setContent(oresponse, &error_text, &line)) {
+    QMessageBox::critical(0, tr("Error"),
+           tr("Invalid return data at line %1: %2.")
+           .arg(line)
+          .arg( error_text));
+    bd_.upgradeErrors++;
+    return;
+  }
+
+  QString response;
+  QString upgradeText;
+
+  if (testing)
+    currentVersion =  "1.3.1"; // for testing
+
+  bool allowBeta = true;  // TODO: come from prefs or current version...
+
+  QDomNodeList upgrades = document.elementsByTagName("update");
+  QUrl downloadUrl;
+  updateStatus_ = updateCurrent;  // Current until proven guilty.
+
+  for (unsigned int i = 0; i < upgrades.length(); i++) {
+    QDomNode upgradeNode = upgrades.item(i);
+    QDomElement upgrade = upgradeNode.toElement();
+
+    QString updateVersion = upgrade.attribute("version");
+    if (upgrade.attribute("downloadURL").isEmpty()) {
+      downloadUrl = "http://www.gpsbabel.org/download.html";
+    } else {
+      downloadUrl = upgrade.attribute("downloadURL");
+    }
+    bool updateIsBeta  = upgrade.attribute("type") == "beta";
+    bool updateIsMajor = upgrade.attribute("type") == "major";
+    bool updateIsMinor = upgrade.attribute("type") == "minor";
+
+    bool updateCandidate = updateIsMajor || updateIsMinor || (updateIsBeta && allowBeta);
+    upgradeText = upgrade.firstChildElement("overview").text();
+    // String compare, not a numeric one.  Server will return "best first".
+    if((updateVersion > currentVersion) && updateCandidate) {
+      bd_.upgradeOffers++;
+      updateStatus_ = updateNeeded;
+      response = tr("A new version of GPSBabel is available.<br />"
+        "Your version is %1 <br />"
+        "The latest version is %2")
+          .arg(currentVersion)
+          .arg(updateVersion);
+      break;
+    }
+  }
+
+  if (response.length()) {
+    QMessageBox information;
+    information.setWindowTitle(tr("Upgrade"));
+
+    information.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+    information.setDefaultButton(QMessageBox::Yes);
+    information.setText(response);
+    
+    information.setInformativeText(tr("Do you wish to download an upgrade?"));
+    information.setDetailedText(upgradeText);
+
+    switch (information.exec()) {
+      case QMessageBox::Yes:
+        // downloadUrl.addQueryItem("os", getOsName());
+        QDesktopServices::openUrl(downloadUrl);
+        bd_.upgradeAccept++;
+        break;
+      default: ;
+        bd_.upgradeDeclines++;
+    }
+  }
+
+  upgradeWarningTime = QDateTime(QDateTime::currentDateTime());
+
+  for (int i = 0; i < formatList_.size(); i++) {
+     formatList_[i].zeroUseCounts();
+  }
+}
diff --git a/gpsbabel/gui/upgrade.cpp b/gpsbabel/gui/upgrade.cpp
deleted file mode 100644 (file)
index 6a7ecd6..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-// -*- C++ -*-
-// $Id: upgrade.cpp,v 1.26 2010-06-19 23:59:06 robertl Exp $
-/*
-    Copyright (C) 2009, 2010  Robert Lipe, robertlipe@gpsbabel.org
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- */
-
-
-#include "babeldata.h"
-#include "format.h"
-#include "upgrade.h"
-#include "../gbversion.h"
-#if HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#if HAVE_UNAME
-#include <sys/utsname.h>
-#endif // HAVE_UNAME
-
-#include <QHttp>
-#include <QMessageBox>
-#include <QDesktopServices>
-#include <QDomDocument>
-#include <QLocale>
-#include <QSysInfo>
-#include <QUrl>
-#include <stdio.h>
-
-#if 0
-static const bool testing = true;
-#else
-static const bool testing = false;
-#endif
-
-UpgradeCheck::UpgradeCheck(QWidget *parent, QList<Format> &formatList,
-                           BabelData& bd) :
-  QObject(parent),
-  http(0), 
-  formatList_(formatList), 
-  updateStatus_(updateUnknown),
-  bd_(bd)
-{
-}
-
-UpgradeCheck::~UpgradeCheck()
-{
-  if (http) {
-    http->clearPendingRequests();
-    http->abort();
-    delete http;
-    http = 0;
-  }
-}
-
-bool UpgradeCheck::isTestMode()
-{
-  return testing;
-}
-
-QString UpgradeCheck::getOsName(void)
-{
-  // Do not translate these strings.
-#if defined (Q_OS_LINUX)
-    return "Linux";
-#elif defined (Q_OS_MAC)
-  return "Mac";
-#elif defined (Q_OS_WIN)
-  return "Windows";
-#else
-  return "Unknown";
-#endif
-
-}
-// See http://doc.trolltech.com/4.5/qsysinfo.html to interpret results
-QString UpgradeCheck::getOsVersion()
-{
-#if defined (Q_OS_MAC)
-  switch (QSysInfo::MacintoshVersion) {
-  case QSysInfo::MV_10_3: return "10.3"; break;
-  case QSysInfo::MV_10_4: return "10.4"; break;
-  case QSysInfo::MV_10_5: return "10.5"; break;
-  case QSysInfo::MV_10_6: return "10.6"; break;
-  case QSysInfo::MV_10_7: return "10.7"; break;
-  //case QSysInfo::MV_10_8: return "10.8"; break;
-  default: 
-    if (QSysInfo::MacintoshVersion == 10) {
-      return "10.8";
-      break;
-    }
-    return QString("Unknown Mac %1").arg(QSysInfo::MacintoshVersion);
-  };
-#elif defined (Q_OS_WIN)
-
-  switch (QSysInfo::WindowsVersion) {
-  // Wildly improbable...
-  case QSysInfo::WV_95: return "95"; break;
-  case QSysInfo::WV_98: return "98"; break;
-  case QSysInfo::WV_Me: return "Me"; break;
-
-  case QSysInfo::WV_4_0: return "NT 4"; break;
-  case QSysInfo::WV_5_0: return "2000"; break;
-  case QSysInfo::WV_5_1: return "XP"; break;
-  case QSysInfo::WV_5_2: return "2003"; break;
-  case QSysInfo::WV_6_0: return "Vista"; break;
-  case QSysInfo::WV_6_1: return "7"; break;
-  default:
-      return "Windows/Unknown";
-  }
-#endif
-  // FIXME: find something appropriately clever to do for Linux, etc. here.
-  return "Unknown";
-}
-
-
-UpgradeCheck::updateStatus UpgradeCheck::checkForUpgrade(
-               const QString &currentVersionIn,
-               const QDateTime &lastCheckTime,
-               bool allowBeta)
-{
-  currentVersion = currentVersionIn;
-  currentVersion.remove("GPSBabel Version ");
-
-  QDateTime soonestCheckTime = lastCheckTime.addDays(1);
-  if (!testing && QDateTime::currentDateTime() < soonestCheckTime) {
-    // Not time to check yet.
-    return UpgradeCheck::updateUnknown;
-  }
-
-  http = new QHttp;
-
-  connect(http, SIGNAL(requestFinished(int, bool)),
-          this, SLOT(httpRequestFinished(int, bool)));
-  connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
-          this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
-
-  QHttpRequestHeader header("POST", "/upgrade_check.html");
-
-  const QString host("www.gpsbabel.org" );
-  header.setValue("Host",  host);
-
-  header.setContentType("application/x-www-form-urlencoded");
-  QLocale locale;
-
-  QString args = "current_version=" + currentVersion;
-  args += "&current_gui_version=" VERSION;
-  args += "&installation=" + bd_.installationUuid;
-  args += "&os=" + getOsName();
-#if HAVE_UNAME
-  struct utsname utsname;
-  if (0 == uname(&utsname)) {
-    args += "&cpu=" + QString(utsname.machine);
-  }
-#endif
-
-  args += "&os_ver=" + getOsVersion();
-  args += QString("&beta_ok=%1").arg(allowBeta); 
-  args += "&lang=" + QLocale::languageToString(locale.language());
-  args += "&last_checkin=" + lastCheckTime.toString(Qt::ISODate);
-  args += QString("&ugcb=%1").arg(bd_.upgradeCallbacks); 
-  args += QString("&ugdec=%1").arg(bd_.upgradeDeclines); 
-  args += QString("&ugacc=%1").arg(bd_.upgradeAccept); 
-  args += QString("&ugoff=%1").arg(bd_.upgradeOffers); 
-  args += QString("&ugerr=%1").arg(bd_.upgradeErrors); 
-  args += QString("&rc=%1").arg(bd_.runCount); 
-
-  int j = 0;
-
-  for (int i = 0; i < formatList_.size(); i++) {
-    int rc = formatList_[i].getReadUseCount();
-    int wc = formatList_[i].getWriteUseCount();
-    QString formatName = formatList_[i].getName();
-    if (rc)
-      args += QString("&uc%1=rd/%2/%3").arg(j++).arg(formatName).arg(rc);
-    if (wc)
-      args += QString("&uc%1=wr/%2/%3").arg(j++).arg(formatName).arg(wc);
-  }
-  if (j && bd_.reportStatistics)
-    args += QString("&uc=%1").arg(j);
-
-  if (false && testing)
-   fprintf(stderr, "Posting %s\n", qPrintable(args));
-
-  http->setHost(host, 80);
-  httpRequestId = http->request(header, args.toUtf8());
-
-  return UpgradeCheck::updateUnknown;
-}
-
-void UpgradeCheck::readResponseHeader(const QHttpResponseHeader &responseHeader)
-{
-  switch (responseHeader.statusCode()) {
-  case 200:                   // Ok
-  case 301:                   // Moved Permanently
-  case 302:                   // Found
-  case 303:                   // See Other
-  case 307:                   // Temporary Redirect
-    // these are not error conditions
-    break;
-
-  default:
-    QMessageBox::information(0, tr("HTTP"),
-           tr("Download failed: %1.")
-           .arg(responseHeader.reasonPhrase()));
-    httpRequestAborted = true;
-    http->abort();
-  }
-}
-
-void UpgradeCheck::httpRequestFinished(int requestId, bool error)
-{
-
-  if (http == 0 || error) {
-    bd_.upgradeErrors++;
-    return;
-  }
-
-  // This is not an error state; it's just the internal state of Qt's network
-  // stack flailing around.
-  if (requestId != httpRequestId) {
-    return;
-  }
-
-  bd_.upgradeCallbacks++;
-  QString oresponse(http->readAll());
-
-  QDomDocument document;
-  int line = -1;
-  QString error_text;
-  // This shouldn't ever be seen by a user.  
-  if (!document.setContent(oresponse, &error_text, &line)) {
-    QMessageBox::critical(0, tr("Error"),
-           tr("Invalid return data at line %1: %2.")
-           .arg(line)
-          .arg( error_text));
-    bd_.upgradeErrors++;
-    return;
-  }
-
-  QString response;
-  QString upgradeText;
-
-  if (testing)
-    currentVersion =  "1.3.1"; // for testing
-
-  bool allowBeta = true;  // TODO: come from prefs or current version...
-
-  QDomNodeList upgrades = document.elementsByTagName("update");
-  QUrl downloadUrl;
-  updateStatus_ = updateCurrent;  // Current until proven guilty.
-
-  for (unsigned int i = 0; i < upgrades.length(); i++) {
-    QDomNode upgradeNode = upgrades.item(i);
-    QDomElement upgrade = upgradeNode.toElement();
-
-    QString updateVersion = upgrade.attribute("version");
-    if (upgrade.attribute("downloadURL").isEmpty()) {
-      downloadUrl = "http://www.gpsbabel.org/download.html";
-    } else {
-      downloadUrl = upgrade.attribute("downloadURL");
-    }
-    bool updateIsBeta  = upgrade.attribute("type") == "beta";
-    bool updateIsMajor = upgrade.attribute("type") == "major";
-    bool updateIsMinor = upgrade.attribute("type") == "minor";
-
-    bool updateCandidate = updateIsMajor || updateIsMinor || (updateIsBeta && allowBeta);
-    upgradeText = upgrade.firstChildElement("overview").text();
-    // String compare, not a numeric one.  Server will return "best first".
-    if((updateVersion > currentVersion) && updateCandidate) {
-      bd_.upgradeOffers++;
-      updateStatus_ = updateNeeded;
-      response = tr("A new version of GPSBabel is available.<br />"
-        "Your version is %1 <br />"
-        "The latest version is %2")
-          .arg(currentVersion)
-          .arg(updateVersion);
-      break;
-    }
-  }
-
-  if (response.length()) {
-    QMessageBox information;
-    information.setWindowTitle(tr("Upgrade"));
-
-    information.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
-    information.setDefaultButton(QMessageBox::Yes);
-    information.setText(response);
-    
-    information.setInformativeText(tr("Do you wish to download an upgrade?"));
-    information.setDetailedText(upgradeText);
-
-    switch (information.exec()) {
-      case QMessageBox::Yes:
-        // downloadUrl.addQueryItem("os", getOsName());
-        QDesktopServices::openUrl(downloadUrl);
-        bd_.upgradeAccept++;
-        break;
-      default: ;
-        bd_.upgradeDeclines++;
-    }
-  }
-
-  upgradeWarningTime = QDateTime(QDateTime::currentDateTime());
-
-  for (int i = 0; i < formatList_.size(); i++) {
-     formatList_[i].zeroUseCounts();
-  }
-}
diff --git a/gpsbabel/gui/version_mismatch.cc b/gpsbabel/gui/version_mismatch.cc
new file mode 100644 (file)
index 0000000..6256029
--- /dev/null
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2010  Robert Lipe <robertlipe@gpsbabel.org
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+
+#include "version_mismatch.h"
+
+VersionMismatch::VersionMismatch(QWidget *parent, const QString &ver1,
+                                 const QString &ver2): QDialog(parent)
+{
+  ui.setupUi(this);
+
+  ui.ClVersion->setText(ver1);
+  ui.ClVersion->adjustSize();
+
+  ui.GuiVersion->setText(ver2);
+  ui.GuiVersion->adjustSize();
+}
diff --git a/gpsbabel/gui/version_mismatch.cpp b/gpsbabel/gui/version_mismatch.cpp
deleted file mode 100644 (file)
index 6256029..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// -*- C++ -*-
-//------------------------------------------------------------------------
-//
-//  Copyright (C) 2010  Robert Lipe <robertlipe@gpsbabel.org
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License as
-//  published by the Free Software Foundation; either version 2 of the
-//  License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
-//  USA
-//
-
-#include "version_mismatch.h"
-
-VersionMismatch::VersionMismatch(QWidget *parent, const QString &ver1,
-                                 const QString &ver2): QDialog(parent)
-{
-  ui.setupUi(this);
-
-  ui.ClVersion->setText(ver1);
-  ui.ClVersion->adjustSize();
-
-  ui.GuiVersion->setText(ver2);
-  ui.GuiVersion->adjustSize();
-}